应传sheet_name=None,它返回以sheet名为键、DataFrame为值的字典;避免用"all"或列表模拟全读,后者易漏新增表且多此一举;合并时用pd.concat(all_sheets.values(), ignore_index=True, sort=False)并可加keys参数保留来源标识。

用 pandas.read_excel() 一次性读取所有 Sheet
直接传入 sheet_name=None 是最常用也最稳妥的方式,它会返回一个 dict,键是 sheet 名,值是对应 DataFrame:
import pandas as pd
all_sheets = pd.read_excel("data.xlsx", sheet_name=None)
注意:不要用 sheet_name="all" 或 sheet_name=["Sheet1", "Sheet2"] 来“模拟”全读——前者会报错 ValueError: sheet_name all is not valid,后者漏掉新增 sheet 就得手动改代码。
常见错误:有人先用 pd.ExcelFile 获取 sheet 名再循环读,看似可控,实则多此一举且易出错(比如重复解析 Excel 文件、忽略空 sheet 的处理逻辑)。
合并多个 DataFrame 时,pd.concat() 的关键参数怎么选
拿到 dict 后,用 pd.concat() 合并是最直接的方案,但必须注意三个参数:
立即学习“Python免费学习笔记(深入)”;
-
ignore_index=True:重置行索引,避免合并后出现重复 0,1,2…0,1,2… -
sort=False:默认会按列名排序,可能打乱你原始字段顺序,关掉更安全 -
keys参数可选:如果想保留来源 sheet 信息,传入keys=list(all_sheets.keys()),会生成 MultiIndex,后续用reset_index(level=0)提升为普通列
示例(带来源标识):
df_combined = pd.concat(
all_sheets.values(),
ignore_index=True,
sort=False,
keys=all_sheets.keys()
).reset_index(level=0).rename(columns={"level_0": "sheet_name"})
不同 Sheet 列名不一致怎么办
真实业务中,各 sheet 往往字段名不同(比如 “客户编号” vs “cust_id”)、列数不同、甚至有缺失列。硬拼接会触发 ValueError: Plan shapes are not aligned。
解决思路不是强行对齐,而是统一列结构:
- 先用
pd.concat(..., join="outer")(默认),自动补NaN缺失列 - 再用
reindex(columns=standard_cols, fill_value="")强制对齐到标准列名表 - 或更实用的做法:在读取每个 sheet 时就做映射,比如
df.rename(columns={"cust_id": "customer_id"})
别依赖 Excel 表头“看起来一样”——大小写、空格、隐藏字符都可能导致列名实际不等价。
大文件性能和内存问题怎么绕开
当 Excel 文件超过 50MB 或含大量公式/样式时,pandas.read_excel() 会卡顿甚至 OOM。此时应换用底层引擎:
- 优先用
engine="openpyxl"(xlsx)或engine="xlrd"(xls,仅支持旧版)——它们比默认xlrd(新版已弃用)或odf更稳定 - 若只需部分 sheet,别用
sheet_name=None,明确指定列表,减少解析开销 - 极端情况(GB 级)考虑用
openpyxl.load_workbook(read_only=True)流式读单元格,但需自己处理数据类型转换
容易被忽略的一点:Excel 里的日期常被读成浮点数(如 44205.0),read_excel() 默认能转,但若用底层库手动读,就得调 datetime.fromordinal() 或 xlrd.xldate_as_datetime() 处理——这一步漏掉,时间字段就废了。


















