根本原因是excel格式需逐单元格构造xml并压缩为zip,导致内存高、io频繁、cpu软编码开销大;而to_parquet直接序列化为列式二进制,跳过xml环节,100万行仅需1–3秒。

导出Excel慢的根本原因是什么
Python用pandas.DataFrame.to_excel()写入大文件(比如百万行以上)时,实际是在调用openpyxl或xlsxwriter逐单元格渲染——不是写二进制流,而是构造XML结构、压缩成ZIP包。内存占用高、IO频繁、CPU软编码开销大,10万行就可能耗时几十秒,百万行常卡住或OOM。
常见错误现象包括:MemoryError、进程长时间无响应、生成的.xlsx打不开、磁盘空间突增数倍(临时XML缓存)。
这不是pandas写法问题,是Excel格式本身的限制。哪怕换engine='xlsxwriter'或加compression='zip'也收效甚微。
to_parquet为什么快得多
to_parquet()直接序列化为列式二进制格式(Apache Parquet),跳过所有XML解析/压缩/解压环节。写入是顺序IO+少量CPU编码(如SNAPPY),100万行通常在1~3秒内完成,文件体积还比.xlsx小50%~80%。
关键优势:
-
dtype保留完整(datetime、category、nullable int等不丢失) - 支持分块写入(
partition_cols)、元数据嵌入(metadata) - 后续读取速度极快(
pd.read_parquet()可只读某几列)
注意:Parquet不是“替代Excel给人看”,而是替代Excel作为中间存储/分析管道。如果你最终仍需发.xlsx给业务方,应把Parquet当缓存层,按需转Excel(且只转筛选后的子集)。
实操:安全替换to_excel的三步
- 直接替换
df.to_excel('out.xlsx')为df.to_parquet('out.parquet', engine='pyarrow', compression='snappy')
- 确保已安装
pyarrow(pip install pyarrow),不要用fastparquet(对复杂类型支持弱)
- 若原逻辑依赖.xlsx路径(如邮件附件),改用
shutil.move('out.parquet', 'out.xlsx')会失败——必须明确区分用途:Parquet用于内部流转,Excel仅用于最终交付
df.to_excel('out.xlsx')为df.to_parquet('out.parquet', engine='pyarrow', compression='snappy') pyarrow(pip install pyarrow),不要用fastparquet(对复杂类型支持弱) shutil.move('out.parquet', 'out.xlsx')会失败——必须明确区分用途:Parquet用于内部流转,Excel仅用于最终交付 容易踩的坑:
- 用
to_parquet()后直接双击文件,系统打不开(它不是Office格式) - 在Windows上路径含中文,未加
use_dictionary=True可能导致写入失败(PyArrow 11+已改善,但仍建议显式指定) - 时间戳列含时区(
datetime64[ns, UTC])时,不加use_deprecated_int96_timestamps=False可能被误读为1970年
什么时候不该换to_parquet
- 最终交付物必须是.xlsx(且对方不会/不能装任何额外工具)
- 数据含合并单元格、条件格式、图表等Excel特有功能(Parquet完全不支持)
- 单次导出量小于1万行,且执行频率低(优化收益远低于引入新依赖的成本)
Parquet快是事实,但它的价值不在“更快导出”,而在于让“导出”这个动作本身变得可忽略——你真正该花时间的地方,是定义好哪些字段要存、分区策略怎么设、下游如何按需查。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











