python 线程池 map_python利用(threading,ThreadPoolExecutor.map,ThreadPoolExecutor.submit) 三种多线程方式处理 list数...

需求:在从银行数据库中取出 几十万数据时,需要对 每行数据进行相关操作,通过pandas的dataframe发现数据处理过慢,于是 对数据进行 分段后 通过 线程进行处理;

如下给出 测试版代码,通过 list 分段模拟 pandas 的 dataframe ;

1.使用 threading模块

1 #-*- coding: utf-8 -*-

2 #(C) Guangcai Ren

3 #All rights reserved

4 #create time '2019/6/26 14:41'

5 importmath6 importrandom7 importtime8 from threading importThread9

10 _result_list =[]11

12

13 defsplit_df():14 #线程列表

15 thread_list =[]16 #需要处理的数据

17 _l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]18 #每个线程处理的数据大小

19 split_count = 2

20 #需要的线程个数

21 times = math.ceil(len(_l) /split_count)22 count =023 for item inrange(times):24 _list = _l[count: count +split_count]25 #线程相关处理

26 thread = Thread(target=work, args=(item, _list,))27 thread_list.append(thread)28 #在子线程中运行任务

29 thread.start()30 count +=split_count31

32 #线程同步,等待子线程结束任务,主线程再结束

33 for _item inthread_list:34 _item.join()35

36

37 defwork(df, _list):38 """线程执行的任务,让程序随机sleep几秒39

40 :param df:41 :param _list:42 :return:43 """

44 sleep_time = random.randint(1, 5)45 print(f'count is {df},sleep {sleep_time},list is {_list}')46 time.sleep(sleep_time)47 _result_list.append(df)48

49

50 defuse():51 split_df()52

53

54 if __name__ == '__main__':55 y =use()56 print(len(_result_list), _result_list)

响应结果如下:

注意点:

脚本中的  _result_list 在项目中 要 放在 函数中,不能直接放在 路由类中,否则会造成 多次请求 数据 污染;

定义线程任务时    thread = Thread(target=work, args=(item, _list,))     代码中的 work函数 和 参数 要分开,否则 多线程无效

注意线程数不能过多

2.使用ThreadPoolExecutor.map

#-*- coding: utf-8 -*-#(C) Guangcai Ren #All rights reserved#create time '2019/6/26 14:41'

importmathimportrandomimporttimefrom concurrent.futures importThreadPoolExecutordefsplit_list():#线程列表

new_list =[]

count_list=[]#需要处理的数据

_l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]#每个线程处理的数据大小

split_count = 2

#需要的线程个数

times = math.ceil(len(_l) /split_count)

count=0for item inrange(times):

_list= _l[count: count +split_count]

new_list.append(_list)

count_list.append(count)

count+=split_countreturnnew_list, count_listdefwork(df, _list):"""线程执行的任务,让程序随机sleep几秒

:param df:

:param _list:

:return:"""sleep_time= random.randint(1, 5)print(f'count is {df},sleep {sleep_time},list is {_list}')

time.sleep(sleep_time)returnsleep_time, df, _listdefuse():

pool= ThreadPoolExecutor(max_workers=5)

new_list, count_list=split_list()#map返回一个迭代器,其中的回调函数的参数 最好是可以迭代的数据类型,如list;如果有 多个参数 则 多个参数的 数据长度相同;

#如: pool.map(work,[[1,2],[3,4]],[0,1]]) 中 [1,2]对应0 ;[3,4]对应1 ;其实内部执行的函数为 work([1,2],0) ; work([3,4],1)

#map返回的结果 是 有序结果;是根据迭代函数执行顺序返回的结果

#使用map的优点是 每次调用回调函数的结果不用手动的放入结果list中

results =pool.map(work, new_list, count_list)print(type(results))#如下2行 会等待线程任务执行结束后 再执行其他代码

for ret inresults:print(ret)print('thread execute end!')if __name__ == '__main__':

use()

响应为:

3.使用 ThreadPoolExecutor.submit

1 #-*- coding: utf-8 -*-

2 #(C) Guangcai Ren

3 #All rights reserved

4 #create time '2019/6/26 14:41'

5 importmath6 importrandom7 importtime8 from concurrent.futures importThreadPoolExecutor9

10 #线程池list

11 pool_list =[]12

13

14 defsplit_df(pool):15 #需要处理的数据

16 _l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]17 #每个线程处理的数据大小

18 split_count = 2

19 #需要的线程个数

20 times = math.ceil(len(_l) /split_count)21 count =022 for item inrange(times):23 _list = _l[count: count +split_count]24 #线程相关处理

25 #submit方法提交可回调的函数,并返回一个future实例;future对象包含相关属性

26 #如: done(函数是否执行完成),result(函数执行结果),running(函数是否正在运行)

27 #从而 可以在submit 后的代码中 查看 相关任务运行情况

28 #此方法 执行数据的结果是无序的,如果需要得到有序的结果,需要 for循环 每个future实例(线程池),如 此脚本代码

29 f =pool.submit(work, item, _list)30 pool_list.append(f)31 count +=split_count32

33

34 defwork(df, _list):35 """线程执行的任务,让程序随机sleep几秒36

37 :param df:38 :param _list:39 :return:40 """

41 sleep_time = random.randint(1, 5)42 print(f'count is {df},sleep {sleep_time},list is {_list}')43 time.sleep(sleep_time)44 returnsleep_time, df, _list45

46

47 defuse():48 pool = ThreadPoolExecutor(max_workers=5)49 split_df(pool)50 _result_list =[]51 for item inpool_list:52 result_tuple =item.result()53 _result_list.append(result_tuple[1])54 return_result_list55

56

57 if __name__ == '__main__':58 _result_list =use()59 print(len(_result_list), _result_list)

结果如下:

个人比较喜欢使用 第二中方法,代码写的少,返回的是有序结果,回调函数结果自动管理在generator中,直接for循环 map的结果即可;不用担心在 项目中多次请求数据污染问题

相关连接:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值