卡死主因是pandas默认全量加载且类型推断失控致内存爆满;需显式指定dtype、parse_dates,用chunksize分块并避免pd.concat全量驻留。

卡死不是偶然,是内存被撑爆后系统强制挂起或Python抛出MemoryError前的典型征兆。根本原因在于pandas默认把整张表当“一块铁”往内存里硬塞,而百万行CSV在内存中常膨胀5–10倍——尤其含字符串、时间列、缺失值时。
为什么pd.read_csv一读就卡住?
它默认做三件高开销的事:自动推断每列类型(object最危险)、全量加载进DataFrame、不压缩稀疏结构。比如100万行×10列的CSV原始约200MB,加载后可能占1.5GB以上内存,8GB机器直接触发swap甚至OOM。
- 字符串列默认转为
object类型:每个字符串单独分配内存对象,无法共享指针 - 时间列未指定
parse_dates:被当作字符串存,后续转datetime还要二次解析+拷贝 - 数值列用
int64/float64:哪怕全是0–100的年龄,也占8字节 - 缺失值统一用
NaN:float64列里每个NaN仍占8字节,int列则被迫升为Int64(nullable)类型
chunksize设多大才不爆内存?
不能拍脑袋设10万或100万。真实安全值取决于单行平均内存占用和你当前空闲RAM。
- 先用
pd.read_csv(filename, nrows=1000)读1000行,再算df.memory_usage(deep=True).sum() // 1000得均值(单位字节) - 假设均值80KB,你有1GB空闲内存,理论极限≈12500行;保守起始用
chunksize=5000,跑通后再试10000 - 绝对不要设
chunksize=None或干脆不设——这等于放弃分块,回到原点 - 监控Python进程RSS(Linux用
top,Windows看任务管理器),别只看Jupyter输出
dtype和parse_dates必须在分块时就指定
如果依赖pandas自动推断,每个chunk都会独立infer一次类型,极易导致同字段在不同chunk中类型不一致——比如某chunk全空值推成float64,另一chunk有字符串变成object,后续pd.concat直接报ValueError: cannot concatenate object of type 'float64'。
librosa 是一个用于音频和音乐分析的 Python 库。它提供了特征提取、频谱分析、节拍跟踪、起始检测和音频可视化的工具,基于 NumPy 和 SciPy 构建,用于科学音频计算。
- 用小样本跑一次
pd.read_csv(filename, nrows=10000).dtypes,把结果转成字典传给dtype参数,例如dtype={'user_id': 'uint32', 'status': 'category'} -
parse_dates必须显式传列名列表,如parse_dates=['event_time'];别指望chunk自己识别 - 对高重复字符串列(如城市、状态码),直接在
read_csv里用dtype={'city': 'category'},比读完再astype省70%内存且避免中间态爆炸
分块后千万别用pd.concat([chunk for chunk in ...])
这个写法会把所有chunk全保留在内存里,完全失去分块意义,等价于没分块。
- 要聚合统计(如按用户求和):每块内先算局部结果
chunk.groupby('user')['amount'].sum(),再pd.concat局部结果,最后.groupby(level=0).sum()收口 - 要清洗后存新文件:用
to_csv(mode='a', header=False)逐块追加写入磁盘,内存只留一个chunk - 绝对避免
df = pd.concat([df, chunk])循环拼接——这是引用链泄漏,df越来越大,GC都救不了
真正卡死的点往往不在计算本身,而在读取阶段的类型失控和chunk拼接时的隐式全量驻留。只要在read_csv第一行就锁死dtype、usecols、parse_dates,并用生成器思维处理chunk,百万行就能稳稳流过内存边界。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










