为什么使用ThreadPoolExecutor时并发不起作用?

2024-04-19 01:12:00 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在编写一个应用程序,用于将excels中的数据(有几个表,7-10MB,大约15万行)插入数据库

pandas.read_excel我想减少等待解析大文件或文件列表的时间。以下代码执行此操作:

# coding : utf-8

import pandas as pd
from datetime import datetime
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor


def meta_job(filename):

    num = int(filename[3])
    print(datetime.now().strftime("[%H:%M:%S:%f]"), end=' ')
    print('%smeta_job(%d) start' % (' ' * num, num))

    _ = pd.read_excel(filename, sheet_name=None)

    print(datetime.now().strftime("[%H:%M:%S:%f]"), end=' ')
    print('%smeta_job(%d) end' % (' ' * num, num))
    return filename


def main(fileNames):
    executor = ThreadPoolExecutor(max_workers=8)
    results = executor.map(meta_job, fileNames)
    for i, res in enumerate(results):
        print(i, res)

if __name__ == "__main__":
    fileNames = ["d[%d]_full_10.xlsx" % i for i in range(8)]
    main(fileNames)

    # do the parse with for loop
    print("*" * 20)
    for i in fileNames:
        meta_job(i)


问题是当我运行上面的代码时,并发方法和for循环几乎同时使用,更糟糕的是for循环使用的时间比并发少。你知道吗

但是,当我将ThreadPoolExecutor更改为ProcessPoolExecutor时,并发速度会更快(30秒而不是2分钟)。以下是输出。你知道吗

  • ProcessPoolExecutor输出
[16:46:38:506226] meta_job(0) start
[16:46:38:586626]   meta_job(2) start
[16:46:38:606732]    meta_job(3) start
[16:46:38:775630]        meta_job(7) start
[16:46:38:654980]     meta_job(4) start
[16:46:38:659215]      meta_job(5) start
[16:46:38:727387]       meta_job(6) start
[16:46:38:534345]  meta_job(1) start
[16:47:03:936892]      meta_job(5) end
[16:47:04:127832]  meta_job(1) end
[16:47:05:585193] meta_job(0) end
0 d[0]_full_10.xlsx
1 d[1]_full_10.xlsx
[16:47:07:104038]     meta_job(4) end
[16:47:10:099222]   meta_job(2) end
2 d[2]_full_10.xlsx
[16:47:10:867077]    meta_job(3) end
3 d[3]_full_10.xlsx
4 d[4]_full_10.xlsx
5 d[5]_full_10.xlsx
[16:47:11:305149]       meta_job(6) end
6 d[6]_full_10.xlsx
[16:47:11:392175]        meta_job(7) end
7 d[7]_full_10.xlsx
********************
[16:47:11:396162] meta_job(0) start
[16:47:25:603109] meta_job(0) end
[16:47:25:603109]  meta_job(1) start
[16:47:38:163148]  meta_job(1) end
[16:47:38:163148]   meta_job(2) start
[16:47:55:602426]   meta_job(2) end
[16:47:55:602426]    meta_job(3) start
[16:48:12:402708]    meta_job(3) end
[16:48:12:404835]     meta_job(4) start
[16:48:26:275334]     meta_job(4) end
[16:48:26:275334]      meta_job(5) start
[16:48:38:156112]      meta_job(5) end
[16:48:38:156112]       meta_job(6) start
[16:48:54:135494]       meta_job(6) end
[16:48:54:138486]        meta_job(7) start
[16:49:10:548779]        meta_job(7) end
  • ThreadPoolExecutor输出
[18:26:22:154206] meta_job(0) start
[18:26:22:154206]  meta_job(1) start
[18:26:22:154206]   meta_job(2) start
[18:26:22:154206]    meta_job(3) start
[18:26:22:157393]     meta_job(4) start
[18:26:22:157393]      meta_job(5) start
[18:26:22:158388]       meta_job(6) start
[18:26:22:159391]        meta_job(7) start
[18:28:41:549298]  meta_job(1) end
[18:28:45:378990]      meta_job(5) end
[18:28:56:916256]     meta_job(4) end
[18:28:57:436046] meta_job(0) end
0 d[0]_full_10.xlsx
1 d[1]_full_10.xlsx
[18:29:13:799117]    meta_job(3) end
[18:29:17:903461]        meta_job(7) end
[18:29:19:081831]       meta_job(6) end
[18:29:19:762531]   meta_job(2) end
2 d[2]_full_10.xlsx
3 d[3]_full_10.xlsx
4 d[4]_full_10.xlsx
5 d[5]_full_10.xlsx
6 d[6]_full_10.xlsx
7 d[7]_full_10.xlsx
********************
[18:29:19:767528] meta_job(0) start
[18:29:39:749447] meta_job(0) end
[18:29:39:752440]  meta_job(1) start
[18:29:56:921441]  meta_job(1) end
[18:29:56:923431]   meta_job(2) start
[18:30:19:906304]   meta_job(2) end
[18:30:19:909290]    meta_job(3) start
[18:30:43:297230]    meta_job(3) end
[18:30:43:299242]     meta_job(4) start
[18:31:02:185841]     meta_job(4) end
[18:31:02:188833]      meta_job(5) start
[18:31:19:322984]      meta_job(5) end
[18:31:19:324980]       meta_job(6) start
[18:31:42:272996]       meta_job(6) end
[18:31:42:275983]        meta_job(7) start
[18:32:05:544849]        meta_job(7) end

我在另一个关于xlrd的问题中看到了一些答案。这是否意味着xlrd不支持并发(不释放GIL)?谢谢!你知道吗


Tags: importfordatetimejobfilenamexlsxstartnum
1条回答
网友
1楼 · 发布于 2024-04-19 01:12:00

^{}使用xlrd实际读取MS Excel文件。^{} source code都是Python代码,因此将始终隐式地保留GIL。因此,在使用线程进行并发时,不会看到太多的加速。还有一个^{}项目用于读取msexcel文件,但这似乎也是一个纯Python项目,因此将具有类似的性能特征

正如@JimNilsson所说,由于GIL是在低级文件IO代码(都是原生C代码)中发布的,您可能会获得一些并发性,但这不太可能

相关问题 更多 >