求助:如何从S3的Zip文件中逐个读取CSV至DataFrame?
解决方案
核心思路
先从S3拉取ZIP包到内存,逐个读取其中的CSV文件为DataFrame,修改后将DataFrame转为CSV格式,再通过内存缓冲区上传回S3目标路径。关键是用BytesIO中转ZIP内文件的内容,避免直接传递_SharedFile对象给boto3,解决兼容性报错问题。
完整代码示例
import boto3 import zipfile from io import BytesIO import pandas as pd # 初始化boto3客户端和资源 s3_client = boto3.client('s3') s3_resource = boto3.resource('s3') bucket = 'your-bucket-name' prefix = 'path/to/your/zip/' # ZIP文件所在的前缀路径 target_prefix = 'target/' # 处理后文件的存放前缀 # 获取ZIP文件的Key(过滤出后缀为.zip的文件) zipped_keys = s3_client.list_objects_v2(Bucket=bucket, Prefix=prefix, Delimiter="/") file_list = [key['Key'] for key in zipped_keys['Contents'] if key['Key'].endswith('.zip')] if not file_list: print("未找到目标ZIP文件") exit() # 读取ZIP文件到内存缓冲区 zip_obj = s3_resource.Object(bucket_name=bucket, key=file_list[0]) buffer = BytesIO(zip_obj.get()["Body"].read()) # 遍历ZIP内的所有文件 with zipfile.ZipFile(buffer, 'r') as z: for filename in z.namelist(): # 仅处理CSV文件,跳过目录或非CSV文件 if not filename.endswith('.csv') or filename.endswith('/'): continue print(f"正在处理: {filename}") # 读取ZIP内的CSV到DataFrame with z.open(filename) as csv_file: df = pd.read_csv(csv_file) # --- 在这里添加你的DataFrame修改逻辑 --- # 示例:新增一列标记修改状态 df['modified_flag'] = 'processed' # 将修改后的DataFrame写入内存缓冲区 output_buffer = BytesIO() df.to_csv(output_buffer, index=False) output_buffer.seek(0) # 重置缓冲区指针到起始位置 # 上传到S3目标路径 s3_client.upload_fileobj( output_buffer, Bucket=bucket, Key=f"{target_prefix}{filename}" ) print("所有CSV文件处理并上传完成")
关键说明
- 解决报错根源:通过
z.open()读取CSV内容到DataFrame后,将修改结果写入新的BytesIO缓冲区,再传给upload_fileobj(),彻底避开_SharedFile与boto3的兼容性问题。 - 过滤无效文件:添加了CSV后缀和目录项的判断,避免处理ZIP内的冗余文件。
- 缓冲区指针重置:必须调用
output_buffer.seek(0),否则upload_fileobj()会从缓冲区末尾读取,导致上传空文件。
内容的提问来源于stack exchange,提问作者PythonDeveloper
相关产品推荐
相关产品推荐

