pandas.read_excel读大excel卡死或爆内存,因默认全量解析xlsx(zip+xml结构),openpyxl引擎内存占用达5–8倍;应改用openpyxl只读模式迭代读取,并手动控制行列范围与提前中断。
为什么 pandas.read_excel 读大文件会卡死或爆内存
因为默认行为是把整个 excel 文件(尤其是含公式、样式、多 sheet 的 .xlsx)全解压、全解析、全载入内存——哪怕你只想要其中一列。excel 的二进制结构(.xlsx 是 zip 套 xml)导致解析开销远高于 csv,openpyxl 引擎尤其吃资源。
- 用
engine='openpyxl'读 10MB 以上文件,内存占用常达原始大小的 5–8 倍 -
read_excel不支持真正的流式读取,chunksize参数对 Excel 无效(仅对 CSV 生效) - 如果文件含大量空行、合并单元格或自定义格式,解析时间会指数级增长
怎么用 openpyxl 迭代读取避免一次性加载
绕过 pandas.read_excel,直接用底层库按需拉取数据。关键不是“快”,而是“可控”——你能跳过不需要的行、列、sheet,也能提前中断。
- 用
load_workbook(filename, read_only=True)启用只读模式,内存占用下降 60%+,且不加载样式/公式 - 通过
wb.active.iter_rows(min_row=2, max_row=1000, values_only=True)指定范围读,values_only=True避免返回 Cell 对象 - 逐行处理时,用
if row[0] is None: break主动跳过空行,比 pandas 的dropna省时省内存
from openpyxl import load_workbook
wb = load_workbook('big.xlsx', read_only=True)
ws = wb.active
for row in ws.iter_rows(min_row=2, max_row=5000, values_only=True):
if row[0] is None: continue
process_row(row) # 自定义处理逻辑
wb.close()
分批导入数据库时,to_sql 批量写入失败或极慢怎么办
to_sql 默认每行一条 INSERT,万级数据就成千上万次网络往返;而批量插入必须靠 method='multi' 或原生 execute + executemany,否则毫无意义。
- 别用
if_exists='append'配合默认method=None,这是最慢路径 - 显式设
method='multi'可让 pandas 拼成一条 INSERT ... VALUES (...),(...),(...),但有长度限制(MySQL 默认 max_allowed_packet) - 更稳的方式:用
engine.execute(text("INSERT INTO ..."))+executemany,自己控制每批 500–2000 行 - 导入前关掉索引和外键检查(PostgreSQL 用
SET CONSTRAINTS ALL DEFERRED,MySQL 用SET FOREIGN_KEY_CHECKS=0),完事后重建
用 xlrd 还是 openpyxl?旧版 Excel(.xls)怎么处理
xlrd 从 2.0 版起已**完全放弃对 .xls 以外格式的支持**,且不再维护;但如果你真要读老式 .xls 文件,只能用它——而且必须锁定 xlrd==1.2.0,新版装不上。
- 读 .xlsx/.xlsm 一律用
openpyxl(推荐)或pyxlsb(处理 .xlsb) - 读 .xls 必须用
xlrd==1.2.0+formatting_info=False(否则内存暴涨) - 不要混用引擎:pandas 的
engine参数传错会导致静默失败或读出乱码,比如engine='xlrd'传了 .xlsx 文件 - .xls 文件本身不压缩,但
xlrd解析时仍会缓存整张表,建议配合sheet_by_name和row_values手动切片
实际操作中,最容易被忽略的是「关闭 workbook」和「及时 del 变量」——openpyxl 的 read_only=True 模式不自动释放文件句柄,反复读多个大文件时会触发 OSError: [Errno 24] Too many open files。











