我正在编写一个应用程序,用于将excels(有几张纸,7-10MB,约15万行)中的数据插入数据库。我用
解析excels 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分钟)。以下是输出。
[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
[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)?谢谢!
答案 0 :(得分:1)
Pandas.read_excel
使用xlrd
来实际读取MS Excel文件。 xlrd
source code是所有Python代码,因此将隐式始终包含GIL。因此,使用线程进行并发时不会看到太多的加速。还有一个用于读取MS Excel文件的openpyxl
项目,但这似乎也是一个纯Python项目,因此具有类似的性能特征
如@JimNilsson所说,由于GIL被发布在低级文件IO代码(全都是本机C代码)中,因此您可能会得到一些并发性,但这并不太可能