openpyxl 读取大型 Excel 文件报错 MemoryError 时,最推荐的处理方向是开启只读模式并配合生成器逐行读取。适用场景为数据量超过 10 万行或文件体积数百 MB 以上,风险边界是只读模式下无法修改原文件且部分公式无法计算。
先说结论:通过调整 load_workbook 参数启用流式读取,可避免全量加载导致的内存溢出。
- 先定位:确认代码是否默认加载了单元格样式和公式对象。
- 先做:在 load_workbook 函数中设置 read_only=True 和 data_only=True。
- 再验证:观察程序运行期间内存占用是否不再随文件大小线性增长。
快速处理思路
直接使用 openpyxl 的只读模式加载工作簿,并通过迭代器逐行获取数据,避免将 entire workbook 对象驻留内存。
from openpyxl import load_workbook
def read_large_excel(file_path):
wb = load_workbook(filename=file_path, read_only=True, data_only=True)
ws = wb.active
for row in ws.iter_rows(values_only=True):
yield row
wb.close()为什么会这样
openpyxl 默认模式会将 Excel 中的所有内容包括单元格格式、公式、图表一次性加载到内存。数据量越大,内存占用越高,最终触发 MemoryError。开启只读模式后,openpyxl 采用生成器模式逐行加载,不一次性存储所有数据,大幅减少内存占用。
分步处理
第一步:安装依赖。确保本地已安装 Python 环境,执行 pip install openpyxl 命令安装库。
第二步:修改加载参数。将代码中的 load_workbook 调用修改为包含 read_only=True 和 data_only=True 参数。
第三步:使用生成器遍历。使用 ws.iter_rows(values_only=True) 替代直接访问 ws.rows,确保返回的是值元组而非单元格对象。
第四步:手动关闭资源。只读模式必须手动调用 wb.close() 释放文件句柄,否则可能导致文件占用。
怎么验证是否生效
运行修改后的脚本,打开系统任务管理器或活动监视器,观察 Python 进程的内存占用。若内存占用稳定在较低水平且不随文件行数增加而暴涨,说明流式读取生效。也可在代码中引入 tracemalloc 模块监控内存分配峰值。
常见坑
只读模式下无法保存修改。若业务逻辑需要写入数据,不能直接使用 read_only=True 打开的工作簿对象进行 save 操作。处理写入大量数据报错时,需安装 lxml 包优化写入性能,或采用分批写入策略。
常见问题
read_only=True 后还能修改单元格吗
不能。只读模式禁止对工作表进行写入操作,如需修改数据需重新创建 Workbook 对象。
pandas 读取大文件有什么替代方案
可以使用 pandas 的 read_excel 函数配合 chunksize 参数实现分块读取,适用于需要数据分析的场景。
参考来源
- 内存溢出频发,Python 读取大 Excel 文件的 4 种工业级应对方案
- 用 Python 操作 Excel:openpyxl 读写大型表格避坑指南
- Python 读取大 Excel 文件卡顿崩溃?揭秘企业级流式处理黑科技-CSDN 博客
- openpyxl 写入 xlsx 大量数据时报错:MemoryError Error in atexit._run_exitfuncs