【发布时间】:2022-06-30 20:00:53
【问题描述】:
我对openpyxl在读取文件时的性能有疑问。
我正在尝试使用 ProcessPoolExecutor 读取相同的 xlsx 文件,单个文件可能有 500,000 到 800,000 行。
在只读模式下调用sheet.iter_rows(),不使用ProcessPoolExecutor时,读取整个工作表,处理10000行数据大约需要1s。但是当我用 ProcessPoolExecutor 设置 max_row 和 min_row 参数时,就不一样了。
totalRows: 200,000
1 ~ 10000 take 1.03s
10001 ~ 20000 take 1.73s
20001 ~ 30000 take 2.41s
30001 ~ 40000 take 3.27s
40001 ~ 50000 take 4.06s
50001 ~ 60000 take 4.85s
60001 ~ 70000 take 5.93s
70001 ~ 80000 take 6.64s
80001 ~ 90000 take 7.72s
90001 ~ 100000 take 8.18s
100001 ~ 110000 take 9.42s
110001 ~ 120000 take 10.04s
120001 ~ 130000 take 10.61s
130001 ~ 140000 take 11.17s
140001 ~ 150000 take 11.52s
150001 ~ 160000 take 12.48s
160001 ~ 170000 take 12.52s
170001 ~ 180000 take 13.01s
180001 ~ 190000 take 13.25s
190001 ~ 200000 take 13.46s
total: take 33.54s
显然,单看每个过程的结果,消耗的时间确实少了。 但是整体时间消耗增加了。 范围越靠后,每个进程消耗的时间就越多。 单个进程读取 200,000 行仅需 20 秒左右。
我对迭代器不是很清楚,也没有仔细研究过openpyxl的源代码。 从耗时来看,即使设置了范围,迭代器仍然需要从第1行开始处理,不知道是不是这样。
我不是专业程序员,如果你恰好有相关经验,请尽量简单
代码在这里!!!
import openpyxl
from time import perf_counter
from concurrent.futures import ProcessPoolExecutor
def read(file, minRow, maxRow):
start = perf_counter()
book = openpyxl.load_workbook(filename=file, read_only=True, keep_vba=False, data_only=True, keep_links=False)
sheet = book.worksheets[0]
val = [[cell.value for cell in row] for row in sheet.iter_rows(min_row=minRow, max_row=maxRow)]
book.close()
end = perf_counter()
print(f'{minRow} ~ {maxRow}', 'take {0:.2f}s'.format(end-start))
return val
def parallel(file: str, rowRanges: list[tuple]):
futures = []
with ProcessPoolExecutor(max_workers=6) as pool:
for minRow, maxRow in rowRanges:
futures.append(pool.submit(read, file, minRow, maxRow))
return futures
if __name__ == '__main__':
file = '200000.xlsx'
start = perf_counter()
tasks = getRowRanges(file)
parallel(file, tasks)
end = perf_counter()
print('total: take {0:.2f}s'.format(end-start))
【问题讨论】:
-
如果您尝试一次读取多张纸,您只能通过并行化获得更好的性能。这在 openpyxl 文档中有所介绍:openpyxl.readthedocs.io/en/stable/performance.html。只是尝试一些东西并期待魔法很少是一个好主意。
标签: python parallel-processing iterator openpyxl