Python批量Excel转CSV提速:更快读取至DataFrame方案咨询
嘿,我来帮你解决这个Excel读取慢的问题!
为什么pandas读取Excel会这么慢?
即使你只需要读取原始数据而不需要样式、颜色,Excel文件的结构特性还是会让解析过程比想象中更耗时:
- xlrd的解析逻辑:pandas默认用xlrd读取
.xls文件,它需要遍历整个文件的内部结构,处理每个单元格的类型(数值、文本、日期等)——哪怕你不需要样式信息,文件里自带的格式元数据还是会被解析,这会额外消耗时间。 - 版本老旧:你使用的pandas 0.21.0和xlrd 1.0.0都是比较早期的版本,后续版本对Excel读取做了大量性能优化,比如减少不必要的元数据解析、优化内存占用逻辑。
- skiprows的额外开销:使用
skiprows参数时,xlrd需要先读取并跳过指定的行,相当于多做了一遍"读取但不保留"的无用功,也会增加耗时。
Python层面的更快替代方案
针对你的700个文件批量处理场景,这里有几个实用的优化方向,按优先级排列:
1. 并行处理多个文件
最立竿见影的优化就是利用CPU多核并行处理文件——毕竟700个文件是独立的,串行处理会浪费大量算力。示例代码如下:
from multiprocessing import Pool import pandas as pd import os def process_single_file(file_path): # 读取文件,跳过指定行 df = pd.read_excel(file_path, skiprows=your_skip_rows, engine="xlrd") # 移除冗余表头、修改列名的逻辑 df.columns = ["新列名1", "新列名2", "新列名3"] # 替换成你的实际列名 # 保存为CSV csv_path = os.path.splitext(file_path)[0] + ".csv" df.to_csv(csv_path, index=False, encoding="utf-8") if __name__ == "__main__": file_list = ["/path/to/file1.xls", "/path/to/file2.xls", ...] # 你的700个文件列表 # 进程数建议设为CPU核心数,比如4或8 with Pool(processes=4) as pool: pool.map(process_single_file, file_list)
2. 优化pandas read_excel的参数
即使不换库,调整参数也能显著提速:
- 只读取需要的列:用
usecols参数指定你需要的列(列索引或列名),避免读取无关列。比如usecols=[0,2,4]或者usecols=["旧列名1", "旧列名3"]。 - 提前指定数据类型:用
dtype参数指定列的类型,避免pandas自动推断类型(推断过程需要逐个检查单元格)。比如dtype={"用户ID": str, "金额": float}。 - 尝试其他引擎:
- 如果是
.xlsx文件,试试engine="openpyxl"(注意Python2.7下要安装openpyxl==2.6.4,更高版本不支持Python2.7):pip install openpyxl==2.6.4,代码改为df = pd.read_excel(file_path, skiprows=your_skip_rows, engine="openpyxl")。 - 如果是
.xlsb二进制文件,用pyxlsb引擎,它的解析速度比xlrd快很多:pip install pyxlsb,代码改为df = pd.read_excel(file_path, skiprows=your_skip_rows, engine="pyxlsb")。
- 如果是
3. 绕过pandas,直接用xlrd读取
如果你不需要DataFrame的复杂操作,直接用xlrd读取数据并写入CSV,能避免pandas构建DataFrame的额外开销。示例代码:
import xlrd import csv import os def excel_to_csv_direct(file_path, skip_rows): workbook = xlrd.open_workbook(file_path) sheet = workbook.sheet_by_index(0) # 假设读取第一个工作表 csv_path = os.path.splitext(file_path)[0] + ".csv" with open(csv_path, "w") as csv_file: writer = csv.writer(csv_file) # 先写入修改后的列名 writer.writerow(["新列名1", "新列名2", "新列名3"]) # 跳过指定行,写入数据行 for row_idx in range(skip_rows, sheet.nrows): writer.writerow(sheet.row_values(row_idx))
4. 升级版本(如果可能)
虽然你用的是Python2.7,但如果能升级到Python3.x,配合新版的pandas(比如1.0+)和xlrd,性能会有明显提升——新版本对Excel读取的解析逻辑做了大量优化,内存占用也更低。不过这可能需要调整代码适配Python3语法。
内容的提问来源于stack exchange,提问作者Azhar
相关产品推荐
相关产品推荐

