最稳方案是glob找文件+pd.read_excel逐个读+pd.concat一次性合并;需统一sheet_name、usecols、dtype,加ignore_index=true,避免循环append或反复concat导致o(n²)性能崩溃。

用 pandas.concat 配合 glob 批量读取,别用循环 append
直接循环调用 df.append() 或反复 pd.concat() 是最慢的写法——每次都会复制整个 DataFrame,时间复杂度接近 O(n²)。正确做法是先收集所有 DataFrame 到列表,再一次性 concat。
- 用
glob.glob("*.xlsx")或pathlib.Path().glob("*.xlsx")获取文件路径列表,比os.listdir更安全(自动过滤隐藏文件) - 对每个文件,用
pandas.read_excel(file, engine="openpyxl")读取;若含多个 sheet,显式指定sheet_name=0或遍历pd.ExcelFile(file).sheet_names - 务必加
ignore_index=True,否则合并后索引重复,后续去重或切片会出错 - 如果各表结构不一致(列名/顺序不同),提前统一列:读取时用
usecols限定列,或读完后用reindex(columns=common_cols, fill_value=np.nan)
内存爆掉?用 chunksize 和 dtype 控制读取粒度
几千个 Excel 文件,哪怕单个不大,叠加后也容易触发 MemoryError。关键不是“怎么快”,而是“怎么不崩”。
-
read_excel不支持chunksize(那是read_csv的),但可以限制每张表只读前 N 行做验证:read_excel(file, nrows=100) - 显式声明
dtype能省 30%–50% 内存:字符串列用"string"(pandas 2.0+)或"category",数值列避免默认float64,改用pd.Int64Dtype()或"float32" - 读完立刻删掉临时变量:
del temp_df,并手动触发gc.collect()(尤其在大循环里) - 如果只是合并后统计,考虑不用全量加载:用
openpyxl直接读单元格值,跳过 pandas 解析开销
合并后列名混乱?用 read_excel 的 header 和 skiprows 对齐结构
很多 Excel 表头不规范:有的带空行,有的第一行是标题但第二行才是字段,有的甚至每张表字段位置都偏移。硬拼会得到错位列。
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
- 先抽样 3–5 个文件,用
pd.read_excel(file, nrows=5)看真实结构,确定统一的skiprows和header参数 - 若表头行不固定,用
pd.read_excel(file, header=None)读成纯数字列,再用.iloc定位标题行,.rename()重命名 - 合并后检查:
result.columns.duplicated().any(),若有重复列名,用add_suffix("_" + filename.stem)区分,但注意后续聚合逻辑是否受影响
为什么不用 ExcelWriter 或数据库中转?
有人想“先写进一个大 Excel 再读”,或“导入 SQLite 再查出来”——这两条路都更慢且易出错。
-
ExcelWriter写入性能极差,且单个 Excel 有行数限制(1048576 行),几千个表大概率超限 - SQLite 中转看似合理,但
to_sql默认逐行插入,没设method="multi"和chunksize会慢十倍;而且多进程写同一 DB 文件需加锁,反而串行化 - 真正适合中转的是
parquet:用df.to_parquet(f"{i}.parq")分别保存,再用pd.read_parquet("*/*.parq")自动合并,速度快、压缩好、类型保留完整
最麻烦的从来不是“怎么合并”,而是“怎么让不同格式、不同质量的 Excel 在合并时不丢数据、不错列、不炸内存”。动手前花十分钟看样本,比写完再调试两小时强得多。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










