使用boto3操作AWS S3时如何高效筛选获取info.json文件的key路径
S3批量获取指定路径下info.json的优化方案
S3的列表查询API本身没有原生的后缀过滤能力,你的原始实现逻辑是可用的,但是在2021前缀下文件数量大的时候会有很多无效遍历,你可以根据你的路径规则选择下面两种更高效的方案:
方案1:固定路径场景(推荐,性能最高)
如果你的info.json固定存放在年/月/二级目录下(和你给出的示例结构一致),可以先拉取月份前缀再直接判断文件是否存在,完全不需要遍历其他嵌套目录的文件,文件量越大性能优势越明显:
import boto3 from botocore.errorfactory import ClientError s3 = boto3.client('s3') bucket_name = 'data-for-seo-adwords-data' info_json_files = [] # 分页拉取2021下的所有月份前缀,用Delimiter过滤子目录 paginator = s3.get_paginator('list_objects_v2') month_pages = paginator.paginate( Bucket=bucket_name, Prefix='2021/', Delimiter='/' ) for page in month_pages: for prefix_item in page.get('CommonPrefixes', []): month_prefix = prefix_item['Prefix'] target_key = f"{month_prefix}info.json" # 直接判断目标文件是否存在 try: s3.head_object(Bucket=bucket_name, Key=target_key) info_json_files.append(target_key) except ClientError as e: # 仅忽略文件不存在的报错,其他错误(如权限不足)正常抛出 if e.response['Error']['Code'] != '404': raise return info_json_files
方案2:路径不固定场景
如果info.json存放的层级不固定,可以优化你的原始实现的过滤逻辑,减少无效操作:
import boto3 s3 = boto3.resource('s3') bucket = s3.Bucket('data-for-seo-adwords-data') # 用列表推导式替代循环append,用endswith精准匹配后缀,删除冗余的print语句 info_json_files = [ obj.key for obj in bucket.objects.filter(Prefix='2021') if obj.key.endswith('info.json') ] return info_json_files
优化点说明
- 去掉了原始代码中冗余的
print语句,IO操作会大幅拖慢遍历速度 - 用
endswith('info.json')替代'info' in obj.key,避免误匹配到路径中包含info字段的其他文件 - 方案1的请求次数仅和月份数量挂钩,和嵌套目录下的文件数量无关,适合桶内文件量较大的场景
内容的提问来源于stack exchange,提问作者ALTAF HUSSAIN
相关产品推荐
相关产品推荐

