使用boto3按CSV中的uuid从S3批量提取文件转存新桶的实现问题
实现方案
整体逻辑:先读取CSV中的UUID列表→针对每个UUID构造S3对象前缀→批量匹配前缀下的所有文件→调用S3内置复制接口直接跨桶转存,无需本地下载上传。
完整代码实现
import boto3 import csv from botocore.exceptions import ClientError # 配置参数 SOURCE_BUCKET = 'BUCKET-NAME' # 源桶名,和你原有代码保持一致 TARGET_BUCKET = 'TARGET-BUCKET-NAME' # 替换为你的目标桶名 CSV_PATH = './uuids.csv' # 替换为你的UUID CSV文件本地路径 FIXED_PREFIX = 'ORG/FOLDER1/' # 固定路径前缀,和你实际路径保持一致 FIXED_SUFFIX = '/DATA/' # UUID后的固定路径后缀 # Create Session session = boto3.Session( aws_access_key_id='ACCESS_KEY_ID', aws_secret_access_key='SECRET_ACCESS_KEY', ) # Initiate S3 Resource s3 = session.resource('s3') source_bucket = s3.Bucket(SOURCE_BUCKET) target_bucket = s3.Bucket(TARGET_BUCKET) # 读取CSV中的所有UUID,自动去重 uuids = set() with open(CSV_PATH, 'r', encoding='utf-8') as f: reader = csv.reader(f) # 如果CSV有表头,取消注释下一行跳过表头 # next(reader) for row in reader: if row: # 跳过空行 uuid = row[0].strip() if uuid: uuids.add(uuid) # 遍历处理每个UUID for uuid in uuids: # 构造查询前缀 search_prefix = f"{FIXED_PREFIX}{uuid}{FIXED_SUFFIX}" print(f"正在处理UUID: {uuid}, 前缀: {search_prefix}") try: # 匹配该前缀下所有文件,无需遍历全桶,效率更高 for obj in source_bucket.objects.filter(Prefix=search_prefix): # 跳过空的文件夹标记对象 if obj.key.endswith('/'): continue # S3服务端直接复制,不占用本地带宽 copy_source = { 'Bucket': SOURCE_BUCKET, 'Key': obj.key } # 目标路径保持和源路径一致,如需调整可修改第二个参数 target_bucket.copy(copy_source, obj.key) print(f"成功复制文件: {obj.key}") except ClientError as e: print(f"处理UUID {uuid} 时出错: {e.response['Error']['Message']}") continue
代码说明
- CSV读取部分默认假设CSV文件每行存储一个UUID、无表头,如果你的CSV有表头或者UUID存放在指定列,调整csv读取的逻辑即可
- 前缀匹配逻辑没有遍历整个源桶的所有对象,而是针对每个UUID构造固定前缀后调用
objects.filter查询,大幅提升查询效率,适合大桶场景 - 跨桶复制直接调用S3服务端复制接口,速度远高于下载再上传的方案
- 内置异常处理,兼容UUID对应路径无文件、复制权限不足等异常场景,不会中断整体任务
注意事项
- 生产环境不要硬编码AWS凭证,推荐使用环境变量、IAM角色(EC2/ECS/Lambda运行时)或者
~/.aws/credentials配置文件读取凭证 - 执行脚本的身份需要拥有源桶的
s3:GetObject权限、目标桶的s3:PutObject权限 - 如果需要修改目标桶的文件存储路径,调整
target_bucket.copy的第二个参数的拼接规则即可 - UUID量较大时可自行添加tqdm进度条、请求限流逻辑避免触发S3接口限流
内容的提问来源于stack exchange,提问作者python_qt
相关产品推荐
相关产品推荐

