使用boto3 upload_fileobj上传至S3仅生成1000个CSV文件,与预期1050个不符的原因排查
问题排查:处理1050个JSON文件仅上传1000个CSV的原因分析
首先可以明确告诉你,这不是upload_fileobj的调用限制导致的——S3的upload_fileobj接口本身没有默认的批量上传数量限制,每次调用都是独立处理单个文件,不会因为调用次数触发1000个的上限。
那问题大概率出在其他环节,我帮你梳理几个最可能的原因:
1. S3列表接口的默认返回限制(最常见!)
你代码里用的s3_client.list_objects接口,AWS默认最多只会返回1000个对象。如果你的1050个JSON文件都在同一个前缀下,第一次调用list_objects只会拿到前1000个,剩下的50个根本没进入循环处理!
这是S3列表接口的设计限制,list_objects(v1版本)默认最大返回数是1000,超过这个数量需要手动分页获取。更推荐用list_objects_v2接口,配合ContinuationToken来遍历所有对象。
2. 部分文件的API请求或下载环节静默失败
虽然你说流程无报错,但可能有些请求环节出现了问题却没被捕获:比如某个API返回的JSON结构不对(比如没有response.snapshotLocation字段)、下载链接失效、网络超时等。如果没有加异常处理,程序会直接跳过这些失败的文件,最终数量就会不足。
3. 文件名重复导致覆盖
如果多个JSON对应的下载文件同名,后面上传的文件会直接覆盖前面的,最终目标路径里的文件数量就会少于实际处理的数量。
修复建议
针对最可能的列表分页问题,给你改一下代码逻辑,同时加上异常处理方便排查:
continuation_token = None while True: # 处理分页逻辑,遍历所有S3对象 if continuation_token: result = s3_client.list_objects_v2( Bucket=bucket_name, Prefix=api_target_read_path, ContinuationToken=continuation_token ) else: result = s3_client.list_objects_v2( Bucket=bucket_name, Prefix=api_target_read_path ) for res in result.get('Contents', []): try: # 读取并解析JSON文件 data = s3_client.get_object(Bucket=bucket_name, Key=res.get('Key')) contents = data['Body'].read().decode('utf-8') json_data = json.loads(contents) json_id = json_data['id'] print(f"正在处理ID: {json_id}") # 调用API获取快照链接 geturl = inv_avail_get_api_url + json_id api_response = requests.get(geturl, headers=headers) api_response.raise_for_status() # 触发HTTP错误异常 durl = api_response.json()["response"]["snapshotLocation"] # 下载目标文件 download_response = requests.get(durl) download_response.raise_for_status() # 触发下载错误异常 # 处理文件名,可选:加上ID避免重复 segments = durl.rpartition('/') file_name = str(segments[2]).split('?')[0] # file_name = f"{json_id}_{file_name}" # 开启这行避免同名覆盖 # 上传到目标S3路径 s3_client.upload_fileobj( BytesIO(download_response.content), bucket_name, api_download_file_path + file_name ) print(f"成功上传: {file_name}") except Exception as e: print(f"处理ID {json_id}失败: {str(e)}") # 可以在这里把失败的ID记录到文件,方便后续重试 # 检查是否还有未遍历的对象 if not result.get('IsTruncated'): break continuation_token = result.get('NextContinuationToken')
总结
优先排查S3列表的分页问题,这几乎是遇到“处理数量卡在1000”的最常见原因。同时通过添加异常处理和日志,能快速定位其他可能的失败环节。
内容的提问来源于stack exchange,提问作者ndev
相关产品推荐
相关产品推荐

