
本文讲解如何正确使用 Python 的 csv 模块将 S3 对象元数据写入 CSV 文件,解决因误用追加模式("a")和循环内重复写入表头导致的重复记录、数据爆炸问题。
本文讲解如何正确使用 python 的 csv 模块将 s3 对象元数据写入 csv 文件,解决因误用追加模式(`"a"`)和循环内重复写入表头导致的重复记录、数据爆炸问题。
在处理批量数据导出(如从 AWS S3 提取对象信息写入 CSV)时,一个常见但极易被忽视的错误是:在 for 循环中以追加模式("a")反复打开文件,并每次写入表头和当前行数据。这正是你遇到重复内容的根本原因——每轮迭代都向 CSV 文件末尾添加一次 account_id;arn 标题行和当前数据,且历史数据永不清理,导致文件随运行次数呈指数级膨胀。
✅ 正确做法:单次创建 + 一次写入表头 + 逐行写入数据
应将 CSV 文件的创建、表头写入与数据写入逻辑分离:仅在脚本开始时以写入模式("w")打开一次文件,写入表头;随后在循环中仅追加数据行。推荐使用 csv.DictWriter,它语义清晰、自动处理字段映射,并确保表头只写一次:
import csv
# 一次性创建新文件(覆盖旧文件),并写入表头
with open("my_file.csv", "w", newline="") as f:
fieldnames = ["account_id", "arn"]
writer = csv.DictWriter(f, fieldnames=fieldnames, delimiter=";", lineterminator="\n")
writer.writeheader() # ← 关键:只在此处写一次表头
# 遍历 S3 对象,逐行写入数据(不重复打开文件)
for obj in my_bucket.objects.filter(Prefix="folderpath"):
key = obj.key
body = obj.get()["Body"].read().decode("utf-8") # ⚠️ 注意:read() 返回 bytes,建议解码为字符串
writer.writerow({"account_id": key, "arn": body})
? 关键修复点说明
- "w" 模式替代 "a":确保每次运行脚本都生成干净的新文件,避免历史数据累积;
- newline="" 参数:防止在 Windows 系统下出现空行(Python 官方 csv 文档强制要求);
- writer.writeheader():由 DictWriter 提供,安全写入表头,且仅执行一次;
- body.decode("utf-8"):obj.get()['Body'].read() 返回 bytes,直接写入 CSV 可能引发编码错误或乱码,务必解码为字符串(根据实际内容编码调整,如 latin-1);
- 避免 writerow(field) + writerows(data) 混用:原代码中每次循环都写标题+单行,是重复逻辑的根源。
? 进阶建议(可选)
- 若需保留历史数据并仅追加新对象,应先读取已有 CSV 获取已处理的 key 列表,再跳过重复项;
- 对于海量对象,可考虑使用 pandas.DataFrame.to_csv(..., mode="a", header=False) 配合批量写入提升性能;
- 增加异常处理(如 try/except 包裹 obj.get()),避免单个对象失败导致整个流程中断。
遵循以上结构,你的 CSV 输出将严格符合预期格式:
account_id;arn key1;body1 key2;body2 key3;body3 ...
简洁、准确、可维护——这才是生产级数据导出的正确打开方式。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











