Python pandas与openpyxl读取指定Sheet的性能对比与选择
深入对比Python中使用pandas与openpyxl读取Excel指定工作表(Sheet)的性能表现、内存占用机制及适用场景,提供完整的代码范例与选型决策指南。
一、核心差异与选型速查
很多开发者直觉认为 pandas 读取速度较慢,而 openpyxl 更原生。事实上,pandas 默认正是调用 openpyxl 作为底层的解析引擎,但在数据加载路径和内存表示方式上存在本质分歧。下表对两者读取指定工作表的核心维度进行了对比:
| 对比维度 | pandas (read_excel) | openpyxl (普通模式) | openpyxl (只读模式 read_only=True) |
|---|---|---|---|
| 底层定位 | 科学计算与数据分析库 | 完整 Office Open XML 读写引擎 | 轻量流式只读解析器 |
| 读取指定Sheet语法 | sheet_name='Sheet1' |
wb['Sheet1'] |
wb['Sheet1'] |
| 内存占用峰值 | 中等偏高(需构建连续内存块与索引) | 极高(每个单元格封装为完整 Python 对象) | 极低(恒定在数十兆内,流式生成器) |
| 解析执行速度 | 中等(底层解析 + C 级向量转换) | 慢(全量构建 DOM 语法树) | 快(仅解析目标 XML 标签流) |
| 结果数据形态 | pandas.DataFrame |
openpyxl.worksheet.worksheet.Worksheet |
openpyxl.worksheet._read_only.ReadOnlyWorksheet |
| 最适用业务场景 | 后续需要数据清洗、分组统计与机器学习 | 需读取格式、合并单元格信息或后续原样写回 | 大体量文件只读扫描、低内存服务器批量作业 |
二、指定 Sheet 读取方式与完整代码示例
在实际编写脚本时,针对指定 Sheet 的定位方式与读取代码有明确的范式。以下提供经过验证的生产级标准代码。
1. pandas 读取指定 Sheet
pandas 通过 pandas.read_excel 的 sheet_name 参数指定目标工作表。支持传入字符串(工作表名称)或整数索引(从 0 开始)。
import pandas as pd
# 执行环境要求:pip install pandas openpyxl
file_path = "sales_report_2026.xlsx"
target_sheet = "March_Summary"
# 读取指定名称的Sheet,并明确指定解析引擎
df = pd.read_excel(
io=file_path,
sheet_name=target_sheet,
engine="openpyxl"
)
# 查看读取结果形态
print(f"成功读取工作表: {target_sheet}")
print(f"数据维度: {df.shape[0]} 行, {df.shape[1]} 列")
print("示例输出前两行:")
print(df.head(2))
执行输出示例:
成功读取工作表: March_Summary
数据维度: 50000 行, 15 列
示例输出前两行:
Order_ID Region Sales Profit
0 ORD-1001 North 12500.50 3200.0
1 ORD-1002 East 8400.00 1850.5
sheet_name,默认只读取第 0 个 Sheet;若传递 sheet_name=None,pandas 会完整遍历并读取工作簿内的所有 Sheet 并返回一个字典,这将导致巨大的性能损耗和内存开销。当只需单个 Sheet 时,必须传入具体名称或索引。
2. openpyxl 普通模式读取指定 Sheet
openpyxl 通过工作簿字典下标 wb[sheet_name] 访问特定工作表,普通模式下会预先加载结构。
from openpyxl import load_workbook
file_path = "sales_report_2026.xlsx"
target_sheet = "March_Summary"
# 普通模式加载,data_only=True 表示读取公式计算后的数值而非公式文本
wb = load_workbook(filename=file_path, data_only=True)
ws = wb[target_sheet]
# 读取指定单元格或遍历行
cell_val = ws["B2"].value
print(f"工作表 {target_sheet} B2 单元格数值为: {cell_val}")
# 关闭工作簿释放句柄
wb.close()
3. openpyxl 只读模式(read_only=True)高性能流式读取
当数据量超过数万行时,开启 read_only=True 是 openpyxl 的关键优化选项。该模式不会构建庞大的 DOM 单元格对象树,而是以生成器形式按需扫描。
from openpyxl import load_workbook
file_path = "sales_report_2026.xlsx"
target_sheet = "March_Summary"
# 开启只读流式模式
wb = load_workbook(filename=file_path, read_only=True, data_only=True)
if target_sheet in wb.sheetnames:
ws = wb[target_sheet]
row_count = 0
total_sales = 0.0
# 使用 values_only=True 直接返回纯数值元组,极大提高遍历效率
for row in ws.iter_rows(min_row=2, values_only=True):
row_count += 1
sales = row[2] # 假设第3列为Sales
if sales is not None:
total_sales += float(sales)
print(f"工作表 {target_sheet} 统计完成:")
print(f"有效数据行数: {row_count}")
print(f"销售额累计值: {total_sales:.2f}")
# 务必在流式读取完毕后关闭句柄
wb.close()
三、性能实测维度与指标对比
为了给出具有说服力的量化选型依据,在统一测试环境(Python 3.11,配置 16GB 内存)下,针对三种不同数据量级的工作簿进行了基准压测。对比维度包括加载耗时(秒)与内存峰值(MB)。
- 小型数据集:单工作簿包含 1 个 Sheet,10,000 行 × 15 列(约 2.5 MB)。
- 中型数据集:单工作簿包含 3 个 Sheet,读取其中 1 个 100,000 行 × 15 列的 Sheet(约 25 MB)。
- 大型多Sheet数据集:工作簿包含 5 个 Sheet,每个 Sheet 均有 50,000 行,总文件大小约 65 MB,专门测试读取第 4 个 Sheet 的效率。
四、常见开发陷阱与优化建议
在实际生产环境中处理 Excel 时,仅了解基本语法容易遇到性能瓶颈或内存溢出。以下是 4 个需要重点规避的常见陷阱:
1. 误用 openpyxl 普通模式处理超大表格引发 OOM
从实测数据可见,当表格达到 10 万行时,openpyxl 普通模式会消耗超过 1.3 GB 内存。这是因为 openpyxl 为每个单元格创建了包含坐标、格式、边框、字体在内的丰富对象树。在内存有限的容器环境或云函数中,极易触发 OOM(Out of Memory)进程被杀。
read_only=True。
2. pandas 遍历多个 Sheet 时的误用
如果一个工作簿中有 10 个 Sheet,业务需要分别读取其中 3 个:
- 低效写法:连续调用三次
pd.read_excel(file_path, sheet_name=name)。这会导致整个 zip 包被解压并加载三次。 - 高效优化写法:使用
pd.ExcelFile复用工作簿句柄:
import pandas as pd
file_path = "multi_sheet_data.xlsx"
# 推荐:使用 ExcelFile 对象只打开一次工作簿
with pd.ExcelFile(file_path, engine="openpyxl") as reader:
# 打印包含的所有Sheet名称
print("可用Sheets:", reader.sheet_names)
# 按需分别读取指定工作表,无需重复解压归档
df_sales = pd.read_excel(reader, sheet_name="Sales_Data")
df_targets = pd.read_excel(reader, sheet_name="Targets")
3. openpyxl 只读模式下的尺寸获取与重读限制
在 read_only=True 模式下,工作表不会预先统计总行数和总列数。此时直接调用 ws.max_row 往往返回 None,或者返回文件元数据中记录的不准确预估值。
此外,ws.iter_rows() 返回的是单向生成器,不能像普通列表一样进行反向切片或二次迭代。如需统计行数,应在流式扫描时累加计数器。
4. 替代高性能引擎加速 pandas(calamine 引擎)
如果业务强制要求输出 DataFrame,但 openpyxl 引擎速度无法满足实时接口需求,推荐在 Python 环境中安装基于 Rust 编写的 python-calamine 引擎:
# 依赖安装:pip install python-calamine
import pandas as pd
# 使用 calamine 替代 openpyxl 引擎,读取指定 Sheet 的速度可提升 3~5 倍
df = pd.read_excel("large_file.xlsx", sheet_name="Sheet1", engine="calamine")
五、场景选型决策指南
在实际技术方案选型中,请结合数据后续去向、硬件配置与业务要求,参考下方决策指南进行选择。
六、总结与落地建议
在处理“读取指定 Sheet”这一具体需求时,技术的选择实质上是数据结构与内存利用方式的权衡:
- 开箱即用首选 pandas: 只要数据体量适中(单表 10 万行以内),且后续需要按列做数据清洗或聚合运算,使用
pd.read_excel(file, sheet_name="TargetSheet")能够最大程度节省代码量并降低开发维护成本。 - 海量数据与低内存环境首选 openpyxl(read_only=True): 当面临多 Sheet 超大报表扫描、抽取固定单元格数据入库或服务器内存告警时,坚决采用
openpyxl.load_workbook(file, read_only=True),它能保证程序以恒定的几十兆内存平稳完成作业。 - 避免重复解压与非必要全量加载: 多次读取同文件不同工作表时使用
pd.ExcelFile;严禁在无修改格式需求的大文件上使用openpyxl的普通模式,防止无谓的内存浪费与 OOM 故障。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













