使用pandas read_excel读取200MB Excel文件耗时超半小时、占用1GB内存的原因分析
read_excel处理200MB Excel文件比Excel慢这么多? 我来帮你拆解一下这个问题——其实pandas和Excel处理大文件的差异,核心在于两者的设计目标和底层实现完全不同,具体原因有这几点:
底层解析引擎的差距:Excel是微软自家的软件,对.xlsx/.xls这些格式有原生的、高度优化的二进制解析逻辑,专门针对自家文件格式做了各种性能优化,处理起来自然高效。而pandas的
read_excel依赖的是第三方库(比如openpyxl、xlrd、pyxlsb),这些库的解析效率和内存管理能力远不如Excel的原生引擎,大文件场景下这种差距会被明显放大。比如旧版xlrd对.xlsx格式的支持有限,openpyxl默认模式下会把整个工作表的结构和数据都加载到内存,这就很吃资源。内存处理策略完全不同:Excel打开文件时采用的是按需加载的策略——它不会一次性把所有数据都塞进内存,只会加载当前可见的工作表、数据块,还会借助虚拟内存做优化,内存占用自然低。但pandas的
read_excel默认会把指定工作表的目标数据完整加载到DataFrame里,而且解析过程中会生成很多中间数据结构,哪怕你用了usecols指定只读取一列,它还是要扫描整个文件的结构来定位目标列,这就导致内存直接飙到1GB,处理速度也慢下来。数据类型推断的额外开销:pandas读取数据时会自动推断每一列的数据类型,这个过程需要扫描大量数据,尤其是当列里存在混合类型时,耗时和内存占用都会飙升。而Excel文件里的数据类型是预先存储好的,打开时直接读取即可,不需要额外做推断,省了大量时间。
文件附加内容的处理差异:如果你的Excel文件里有隐藏行、合并单元格、公式、复杂格式(条件格式、单元格样式)、图表这些内容,pandas依赖的解析库会尝试处理这些结构(哪怕你根本不需要),而Excel软件可以高效地忽略或者延迟加载这些非数据内容,自然更快。比如你用了
skiprows参数,pandas需要先逐行解析前面的行来跳过它们,而Excel可以直接定位到目标行,跳过这个耗时的过程。
read_excel性能的实用方案 针对你的情况,给你几个实际可行的优化方法:
换用更高效的解析引擎:
如果你的文件是.xlsb二进制格式,直接用engine='pyxlsb',这个库专门针对二进制Excel做了优化,速度和内存占用都会大幅降低;如果是.xlsx格式,试试openpyxl的只读模式:df = pd.read_excel(path, sheet_name=0, usecols=[0], skiprows=row_index, engine='openpyxl', read_only=True)提前指定数据类型:
手动指定目标列的数据类型,避免pandas自动推断,能省不少扫描时间:df = pd.read_excel(path, sheet_name=0, usecols=[0], skiprows=row_index, dtype={0: 'object'})分块读取数据:
用chunksize参数把文件分成小块读取,每次处理一部分数据,降低内存压力:chunk_iter = pd.read_excel(path, sheet_name=0, usecols=[0], skiprows=row_index, chunksize=10000) df_list = [] for chunk in chunk_iter: df_list.append(chunk) df = pd.concat(df_list)预处理文件简化结构:
先用Excel软件把不需要的工作表、格式、公式、图表都删掉,只保留需要的数据列,再保存成干净的文件给pandas读取;或者直接把文件另存为.csv格式,pandas的read_csv比read_excel快得多,因为CSV是纯文本格式,解析逻辑更简单。
内容的提问来源于stack exchange,提问作者Mahalingam Sundararaj

