chunksize参数必须与iterator=True配合使用,否则被静默忽略;它指定每次读取的行数,返回TextFileReader可迭代器,需用get_chunk()或安全循环逐块处理。

chunksize参数到底传给谁?不是pandas.read_csv()的独立参数
很多人以为chunksize是pandas.read_csv()的一个可选开关,其实它必须和iterator=True配合使用——否则会被静默忽略。不加iterator=True时,即使写了chunksize=10000,read_csv()仍会一次性加载全部数据到内存,毫无分块效果。
正确写法只有这一种:pd.read_csv("data.csv", chunksize=5000, iterator=True)。返回的是一个TextFileReader对象,本质是可迭代器,不是DataFrame。
- 必须显式写
iterator=True,不能省略 -
chunksize单位是行数,不是字节数或MB - 若CSV含header,每个chunk都自动带列名,无需额外处理
- 如果文件编码异常(如含BOM),需同步传
encoding="utf-8-sig",否则首chunk可能报UnicodeDecodeError
怎么安全地遍历chunk而不崩?别直接for chunk in reader
看似自然的for chunk in reader:在某些场景下会出问题:比如你在循环里调用了chunk.to_sql()并中途报错,迭代器状态就丢了,后续chunk无法继续读取;或者你用break提前退出,底层文件句柄可能没被释放。
更稳妥的做法是用try/except包裹每次get_chunk()调用,并手动控制迭代:
reader = pd.read_csv("big.csv", chunksize=10000, iterator=True, encoding="utf-8-sig")
while True:
try:
chunk = reader.get_chunk()
# 处理chunk:过滤、转换、写入数据库等
process(chunk)
except StopIteration:
break
except Exception as e:
print(f"处理chunk时出错: {e}")
continue
-
get_chunk()比for循环更可控,适合需要错误跳过或日志记录的场景 - 每次
get_chunk()返回一个独立DataFrame,修改它不会影响后续chunk - 若用
for循环,建议配合contextlib.closing()确保资源释放(尤其在Jupyter中反复运行时)
分块后merge或concat很慢?别等所有chunk读完再拼
有人习惯先用list(reader)把所有chunk存成列表,再pd.concat(chunks)——这等于又把全部数据拉进内存,彻底失去分块意义。真正高效的做法是边读边处理,比如边统计、边写磁盘、边流式入库。
创建 Flask + Vue.js 全栈项目,采用单端口架构、uv 依赖管理、结构化日志和生产级前端设计。当用户要求以下操作时触发:创建新的 Flask+Vue 项目、搭建 Web 应用、构建全栈 Python+Vue 应用、初始化 Flask Web 项目、设置单端口 Flask 前后端项目。触发词:新建项目、创建项目、搭建项目、Flask项目、Vue项目。
典型反模式:all_chunks = list(reader); df = pd.concat(all_chunks) → 内存爆掉。
- 需要全局统计(如sum、mean)?用累加变量:
total_rows += len(chunk)、sum_col_a += chunk["a"].sum() - 要写新CSV?用
mode="a"追加,首次写时加header=True,后续设header=False - 要写数据库?每个chunk单独
to_sql(..., if_exists="append"),避免构造超大DataFrame - 如果真需要合并后分析,优先考虑Dask或Polars,而不是硬拼pandas
chunksize设多少才合适?别盲目套用10000
设太大,单个chunk仍可能OOM;设太小,I/O开销剧增,且pandas初始化开销占比升高。实际值取决于你的机器内存、CSV行宽(列数+字符串长度)、以及后续操作复杂度。
经验法门:先用head -n 10000 big.csv | wc -c估算1万行占多少字节,再按可用内存的1/5~1/3反推合理chunksize。例如内存16GB,预留4GB给系统和其他进程,剩下12GB,若1万行≈10MB,则chunksize可设为50000~100000。
- 含大量长文本列(如日志、JSON字符串)时,chunksize要大幅下调
- 使用
usecols只读必要列,能显著降低单chunk内存占用 - 启用
dtype指定列类型(如"category"代替"object"),比默认推断节省50%+内存 - 测试时加
memory_profiler或psutil.Process().memory_info().rss实时观察峰值
分块读取不是银弹,关键在“边读边扔”——一旦chunk完成处理,就让它被GC回收。任何试图把它攒起来的操作,都在悄悄把你带回内存爆炸的老路。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










