设chunksize不自动省内存,真正爆内存的是TextFileReader误用和类型失控;需试读测内存反推合理值,警惕高基数列,正确使用迭代器,及时释放引用,配合dtype、usecols等配置保命。

直接设 chunksize 不会自动省内存,真正爆内存的往往不是文件本身,而是你对 TextFileReader 的误用和类型失控。
chunksize 值怎么算才不白设
设 chunksize=10000 只控制行数,不控制内存。一行含长文本的 object 列,可能比 10 行 int32 还占内存。
- 先试读:用
pd.read_csv(filename, nrows=5000)加载前 5000 行 - 测内存:运行
df.memory_usage(deep=True).sum() / 1024**2得到 MB 数(比如 120 MB) - 反推:若目标单块内存上限是 500 MB,则合理
chunksize ≈ 500 / 120 * 5000 ≈ 20000 - 特别警惕高基数列(如
user_agent、日志 ID)、重复长字符串——它们会让单块内存陡增
TextFileReader 不是 DataFrame,别当对象直接调方法
pd.read_csv(..., chunksize=N) 返回的是 TextFileReader,本质是迭代器。常见错误就是把它当 DataFrame 用。
-
reader = pd.read_csv('x.csv', chunksize=5000); print(reader.shape)→AttributeError - 想预览第一块?用
first_chunk = next(pd.read_csv('x.csv', chunksize=5000)),但注意它已消耗第一个 chunk - 循环必须写成
for chunk in pd.read_csv(..., chunksize=N): ...,不能转成list()或dict()
每块处理完必须立刻丢引用,别攒着拼接
最常踩的坑是把每个 chunk .append() 进列表,或反复 pd.concat()——这等于在内存里重建全量数据,GC 来不及回收。
立即学习“Python免费学习笔记(深入)”;
- 流式写 CSV:
chunk.to_csv('out.csv', mode='a', header=first_write),首次header=True,后续mode='a' - 流式入库:
chunk.to_sql('table', con, if_exists='append', index=False),确保con是 SQLAlchemy 引擎(带连接池) - 真要聚合?只存标量:
sums.append(chunk['sales'].sum()),而不是all_chunks.append(chunk) - 显式释放:
del chunk+gc.collect()(大文件下建议加,尤其 Windows)
dtype 和 usecols 不是可选,是保命配置
默认 object 类型和全列加载,是内存杀手。不指定 dtype,pandas 会把整数当 int64、字符串塞进 Python object;不加 usecols,300 列日志里你只用 3 列,却仍加载全部。
- 强制降级:
dtype={'score': 'float32', 'status': 'uint8'} - 分类压缩:
'city': 'category'对重复值多的列可省 70%+ 内存 - 跳列必写:
usecols=['id', 'amount', 'ts'],比读完再drop省 30%+ 内存 - 禁用索引:
index_col=False,除非真需要行号做索引
真正卡住的点往往不在 chunk 大小,而在于你是否让每一块都「干净退出」:没残留引用、没隐式类型膨胀、没跨块依赖。一旦开始累积或延迟处理,分块就失去了意义。


















