chunksize参数需在pandas.read_csv()或read_json()中直接传入,设为正整数(如10000)才有效;设为None或遗漏则全量加载;逐块处理时须避免累积引用、禁用pd.concat拼接、及时del+gc.collect,且不适用于跨块操作。

chunksize 参数在哪设、怎么设才有效
直接在 pandas.read_csv() 或 pandas.read_json() 里传 chunksize,它不是返回一个 DataFrame,而是返回一个 TextFileReader 迭代器。不这么用,chunk 就白设了——很多人读完第一块就直接 .head() 或 .shape,结果整个文件还是被加载进内存。
-
chunksize=10000表示每次读 1 万行,内存占用大致正比于该数字 × 列数 × 平均每单元格字节数 - 别设成
chunksize=None或漏掉参数:那等价于全量读取 - 如果文件含超长文本列(如日志、HTML 片段),实际内存可能远超预估,建议先用
head -n 1000抽样看字段长度分布
逐块处理时常见的 OOM 残留原因
即使用了 chunksize,仍 OOM,大概率是“块没及时释放”或“中间对象堆积”。Python 的垃圾回收不保证立刻回收,尤其当有隐式引用时。
- 避免在循环内拼接
pd.concat([df_list]):这会把所有 chunk 全存进df_list,等于又全载入了 - 不要写
for chunk in reader: result = chunk[...].groupby(...).sum()然后反复赋值给同一个result——旧result若参与过计算(比如调过.merge()),可能被缓存引用 - 显式触发清理:
del chunk+gc.collect()在关键循环尾部有用,但别滥用;优先靠重构逻辑规避累积
替代方案:什么时候不该用 chunksize?
chunksize 适合“单次扫描+无状态聚合”,比如统计每列缺失数、按某列分组求和。一旦需要跨块关联(如去重全局 ID、窗口函数、前后行比较),它反而让代码更脆弱、内存更难控。
- 要 dedupe 全局唯一 ID?用
sqlite3建临时表,INSERT OR IGNORE写 chunk,比 Python 集合去重省内存得多 - 要做时间序列差分?先用
awk或sed预处理出带 lag 行的文件,再读;或者改用dask.dataframe,它对跨块操作有原生支持 -
chunksize无法跳过坏行重试:遇到编码错误或列数不匹配,整块会报错;此时error_bad_lines=False(旧版)或on_bad_lines='skip'(新版)必须同步配好
验证是否真有效:三步快速自检
别只信 top 或任务管理器里的瞬时内存峰值——得看稳定态。启动脚本前先记下 psutil.Process().memory_info().rss,循环中每处理 5 块打一次日志,观察 RSS 是否收敛在某个平台(比如始终 ≤ 200MB),而不是持续爬升。
立即学习“Python免费学习笔记(深入)”;
- 加一行
import psutil; print(f"RSS: {psutil.Process().memory_info().rss / 1024 / 1024:.1f} MB")在 chunk 处理循环内 - 用
cat huge.csv | head -n 50000 | python script.py快速验证小样本行为 - 如果 RSS 每轮涨几十 MB 不回落,检查有没有意外创建了大
list、dict或没 close 的文件句柄


















