You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

同位置复制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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 18:48:04