根本原因是openpyxl默认DOM模式构建全量XML树且每行实例化大量对象,导致内存暴涨与GC风暴;启用xlsxwriter的constant_memory=True可转为流式写入,内存恒定约80MB。

为什么 to_excel 写入百万行就卡死
根本原因不是 Python 慢,而是 pandas 默认用 openpyxl 引擎写入时,每写一行都触发 XML 节点构建 + 样式对象初始化 + 单元格对象实例化。100 万行 × 20 列,意味着生成上千万个 Python 对象,内存暴涨且 GC 压力大。更关键的是,openpyxl 默认以 DOM 方式构建整个工作簿树结构,写完才序列化成 .xlsx —— 这过程无法流式释放,容易触发 MemoryError 或系统 OOM Killer 杀进程。
改用 xlsxwriter 引擎必须加 constant_memory=True
这是提速最关键的一步,但很多人漏掉。xlsxwriter 本身不走 DOM,但默认仍会缓存整张表的格式状态;启用 constant_memory=True 后,它转为纯流式写入:边写边 flush 到磁盘,内存占用几乎恒定(实测 150 万行仅占 ~80MB)。
正确写法:
with pd.ExcelWriter('out.xlsx', engine='xlsxwriter',
engine_kwargs={'options': {'constant_memory': True}}) as writer:
df.to_excel(writer, index=False)
注意:constant_memory=True 会禁用某些高级功能,比如不能在写入中途插入图表、不能动态设置某列宽度后再写数据——所有格式需提前定义或放弃。
立即学习“Python免费学习笔记(深入)”;
to_csv 真的比 to_excel 快几十倍?看场景
是的,但只在「纯数据导出」场景下成立。CSV 是纯文本流,无格式、无类型推断、无 XML 封装,to_csv 底层调用 C 实现的 fastcsv,写入 100 万行通常在 1–3 秒内完成。
不过要注意几个现实约束:
- 如果你的数据含公式、合并单元格、条件格式、颜色或自定义字体——CSV 根本存不了,硬转等于丢信息
- Excel 打开大 CSV 文件时会自动触发「文本导入向导」,列类型常被误判(如把带前导零的 ID 当数字),需额外加
dtype=str或用 Excel 的「从文本/CSV 导入」功能手动指定 - 超过 1048576 行(Excel 行数上限)的 CSV,Excel 只能打开前 1048576 行,其余截断——这时得切分文件或换数据库
真正该警惕的「伪优化」操作
很多教程推荐「分 chunk 写入 + ExcelWriter 循环 to_excel」,这反而更慢。因为每次 to_excel(sheet_name='Sheet1') 都会重建 worksheet 对象,重复初始化样式表、共享字符串池等开销。
真正有效的做法只有两个方向:
- 内存够:直接
df.to_excel(..., engine='xlsxwriter', ...)一气呵成,别拆 - 内存紧:用
chunksize配合xlsxwriter.Workbook原生 API 手动写,控制每批 append 的行数,避免 pandas 中间转换
最后提醒一句:当数据稳定超过 50 万行,就该质疑「是否真需要 Excel」——CSV + SQLite + DuckDB 组合,往往比 Excel 更快、更稳、更易自动化。



















