同位置复制S3对象清除Glue书签时CopyObject接口报错如何解决
错误原因
你触发报错是因为S3禁止无属性变更的同路径对象复制操作,未修改元数据、存储类、加密属性等配置的前提下,直接调用copy_from复制对象到自身路径会被S3判定为非法请求。
Glue书签识别S3新文件的核心逻辑是判断对象的最后修改时间,你只需要更新目标对象的最后修改时间即可实现需求,无需修改文件名。
修正后代码
import boto3 import datetime print('Loading function') s3 = boto3.resource('s3') glue = boto3.client('glue') bucket='my-bucket' bucket_prefix='my-prefix' def lambda_handler(_event, _context): my_bucket = s3.Bucket(bucket) product_key = None # 遍历前缀下的对象 for object_summary in my_bucket.objects.filter(Prefix=bucket_prefix): product_key= object_summary.key print(f"找到目标对象: {product_key}") break if not product_key: print(f"前缀{bucket_prefix}下未找到匹配对象,跳过处理") return # 复制时添加动态元数据,强制S3更新对象属性和最后修改时间 s3.Object(bucket, product_key).copy_from( CopySource={'Bucket': bucket, 'Key': product_key}, # 新增动态元数据,每次执行都会变化 Metadata={'last_refresh_time': str(datetime.datetime.now().timestamp())}, # 必须指定REPLACE,否则元数据不会更新 MetadataDirective='REPLACE' ) print(f"已成功刷新对象{product_key}的最后修改时间,Glue书签将识别为新文件")
代码说明
- 新增了空对象判断逻辑,避免前缀下无文件时的报错
- 调用
copy_from时添加了动态生成的自定义元数据,同时指定MetadataDirective='REPLACE'触发S3更新对象属性,既规避了同路径复制报错,也更新了对象的最后修改时间 - 删除了原代码中逻辑错误的
delete操作,原操作会尝试删除前缀本身,不符合你保留单个文件的需求
可选替代方案
如果不希望修改对象元数据,也可以采用先下载再覆盖上传的方式实现,适合文件体积较小的场景:
# 读取对象内容再重新上传,自动更新最后修改时间 obj = s3.Object(bucket, product_key) content = obj.get()['Body'].read() obj.put(Body=content)
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

