Python处理大Excel文件:openpyxl性能瓶颈与xlrd替代方案

认真发呆
认真发呆
发布时间:2026-10-13 | 4人浏览过
原创

本文针对Python处理大型Excel文件时openpyxl读取缓慢的问题,通过对比测试分析了openpyxl与xlrd的性能差异。指出openpyxl基于遍历的读取机制导致大文件处理耗时显著增加,而xlrd采用类似数组的下标访问方式,读取速度更稳定。文章提供了具体的性能测试代码、结果对比以及一个用于监控函数运行时间的装饰器示例,为处理百万行级Excel数据提供了实用的技术参考。

Python大Excel文件性能优化方案

为了节省篇幅,这里直接展示核心代码与测试过程。

Talk is cheap, show me the code.


  from openpyxl import Workbook
  from openpyxl.utils import get_column_letter
  from openpyxl import load_workbook
  import time
  wb = load_workbook("E:/a.xlsx", read_only=True)
  sh = wb["Sheet"]
  # rowItem = {}
  # for j in range(1,2000):
  #   for i in range(1, 30):
  #     rowItem[get_column_letter(i)] = i
  #   sh.append(rowItem)
  # wb.save("E:/a.xlsx")
  t0 = time.time()
  print(sh['V500'].value)
  t1 = time.time()
  print("openpyxl所用时间:", str(t1-t0))

  import xlrd
  xlsPath = "E:/a.xlsx"
  WorkBook = xlrd.open_workbook(xlsPath)
  sh = WorkBook.sheet_by_name("Sheet")

  t0 = time.time()
  print(sh.cell(499,22).value)
  t1 = time.time()
  print("xlrd所用时间:", str(t1-t0))

以下是具体的测试结果数据:


22
openpyxl所用时间: 0.44217610359191895
23.0
xlrd所用时间: 0.0010063648223876953

openpyxl与xlrd性能对比分析

测试结论分析

openpyxl在处理大文件时的主要瓶颈在于读取速度。针对这一痛点,可以考虑使用xlrd库进行替代,详细的测试数据与分析将在下文展开。

之所以没有直接采用xlwt配合xlrd的方案,是因为xlwt仅支持Excel 2003及更早版本,其最大行数限制为65536行,无法满足大规模数据需求。相比之下,openpyxl支持Excel 2007+格式,可处理约一百多万行的数据,因此在行数要求较高时更具优势。

在开发工具的过程中遇到了这一性能问题。起初使用xlwt和xlrd组合,当数据行数超过限制后,被迫切换至使用openpyxl处理Excel 2007格式的文件。原本测试不到三万行的数据,使用openpyxl耗时数分钟,具体时长未精确记录。通过添加函数运行时间监视器后,确认性能瓶颈主要出现在数据读取阶段。

读取机制差异与性能瓶颈原因

关于性能差异的原因推测如下:

openpyxl在根据行号和列号读取数据时,底层机制是从第一行第一列开始遍历,直到定位到指定的行号和列号。因此,目标单元格的位置越靠后,遍历次数越多,读取速度越慢(即便从第一个有数据的单元格开始计算也是如此)。而xlrd的读取机制类似于数组访问,通过下标直接定位到内存中的对应地址,因此无论Excel文件的总数据量大小如何,读取特定单元格的速度基本保持不变。

潜在限制与注意事项

遗留问题与注意事项

虽然xlwt写入仅限制在65536行,但需留意xlrd读取时是否也存在类似的行数限制,即超过该数量的数据可能会导致读取错误。

在本案例中,由于业务逻辑是将多表数据合并生成单表数据,生成逻辑大致为Na*Nb的形式。因此,实际读取的源数据量并不大,但生成的数据量巨大。基于这种场景,上述关于读取速度的问题对整体性能影响较小,可以暂时忽略。

另外,有观点指出xlrd在读取xlsx格式文件时偶尔会出现兼容性问题。由于目前尚未进行专门测试且当前使用正常,该问题暂时未被深入排查。

函数运行时间监控工具

最后,分享一个用于监控函数运行时间的Python装饰器代码:


import time
from functools import wraps

def fn_timer(function):
  @wraps(function)
  def function_timer(*args, **kwargs):
    t0 = time.time()
    result = function(*args, **kwargs)
    t1 = time.time()
    print ("Total time running %s: %s seconds" %
      (function.__name__, str(t1-t0))
      )
    return result
  return function_timer

使用方法非常简单,只需在需要监控执行时间的函数定义上方添加@fn_timer装饰器即可。

以上关于解决Python执行较大Excel文件时openpyxl性能缓慢问题的内容分享给大家,希望能为遇到类似问题的开发者提供参考。如果觉得有用,欢迎支持本站。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表