用 chunksize 参数可流式读取超大CSV,返回TextFileReader迭代器,每次yield一个DataFrame;chunksize单位为行数,建议设1000–10000;需显式迭代,避免直接调用.shape等方法。

用 pandas.read_csv() 的 chunksize 参数最省心
直接用 pandas.read_csv() 读超大 CSV 很容易 OOM,但加个 chunksize 就能流式处理。它不一次性加载全部数据,而是返回一个 TextFileReader 迭代器,每次 yield 一个 DataFrame。
关键点:chunksize 单位是行数(不是字节),设太小会频繁 IO、设太大仍可能爆内存。实测从 1000 到 10000 是较稳的区间,具体看单行平均大小和可用内存。
- 必须显式迭代,不能直接对 reader 做
.shape或.head() - 如果需要跳过某几行,用
skiprows,但别和chunksize混用——skiprows是全局跳过,不影响 chunk 划分逻辑 - 列名若不在首行,务必传
header=None并手动设names=...,否则每 chunk 都会把第一行当列名
for chunk in pd.read_csv('huge.csv', chunksize=5000):
process(chunk) # chunk 是 DataFrame,可直接 .apply / .groupby真·逐行解析用 csv.reader + open(),绕过 pandas 开销
当只需要检查某几列、做简单过滤或转成其他格式(比如写入数据库),csv.reader 比 pandas 快 3–5 倍,内存占用几乎恒定。
注意:它返回的是 list(每行字符串列表),不是 DataFrame,也不自动类型转换。你需要自己处理缺失值、引号、换行符嵌套等。
立即学习“Python免费学习笔记(深入)”;
- 务必用
newline=''打开文件,否则在 Windows 下可能误判行尾 -
csv.reader默认不跳过空行,需手动if not row: continue - 如果 CSV 有 header,用
next(reader)提前消费掉,别让它进循环 - 数值列要转
float/int?先try/except,CSV 里常混着'N/A'或空字符串
with open('huge.csv', newline='') as f:
reader = csv.reader(f)
next(reader) # skip header
for row in reader:
if len(row) < 3: continue
try:
val = float(row[2])
except (ValueError, IndexError):
continue遇到 UnicodeDecodeError 别硬扛,先查编码再指定
超大 CSV 经常是 Excel 导出的,实际编码可能是 gbk、gb2312 或 utf-8-sig。直接用默认 utf-8 会报错,且错误位置往往在文件中后段,很难定位。
- 用
file命令(Linux/macOS)或chardet库快速探测:chardet.detect(open('huge.csv', 'rb').read(10000)) -
utf-8-sig是常见坑点:Excel 保存 UTF-8 时会加 BOM,Python 用普通utf-8读会把 BOM 当乱码;改用encoding='utf-8-sig'自动剥离 - Windows 记事本另存的 CSV,大概率是
gbk,别猜,直接试
内存还是涨?检查是否无意触发了全量缓存
即使用了 chunksize 或 csv.reader,内存也可能缓慢上涨——大概率是你在循环里不断 .append() 到某个 list,或者用了 pd.concat() 把所有 chunk 合并。
- 避免在循环内累积数据:想统计就用变量累加,想写文件就边读边写,别攒着
-
pd.concat([df1, df2, ...])在 chunk 循环里调用,等于又把全部数据拉进内存;改用to_sql(..., if_exists='append')或to_csv(..., mode='a') - 用
gc.collect()强制回收没用的 chunk 对象?通常没必要;更该检查是否引用泄露(比如把 chunk 存进了全局 list 或日志对象)
真正超大文件(>10GB)的稳定处理,核心不是“怎么读”,而是“读完立刻丢”。留着任何中间结构,都可能让内存曲线悄悄爬升。


















