python-day37--concurrent.futures模块 实现进程池与线程池

1.concurrent.futures模块 直接内置就是 异步的提交   ,如果你想同步也可以实现(p.submit(task,i).result()即同步执行)

2.属性和方法:

  1.submit   提交     

  2.shutdown  关闭池的入口  等池运行结束    

 1 #进程池
 2 from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
 3 import os,time,random
 4 def task(n):
 5     print('%s is running' %os.getpid())
 6     time.sleep(2)
 7     return n**2
 8 
 9 if __name__ == '__main__':
10     p=ProcessPoolExecutor()
11     l=[]
12     start=time.time()
13     for i in range(10):
14         obj=p.submit(task,i)
15         l.append(obj)
16     p.shutdown()
17     print('='*30)
18     # print([obj for obj in l])      # 结果 都是 future 的对象  [<Future at 0x1461d97d1d0 state=finished returned int>,
19                                             # <Future at 0x1461d9c6438 state=finished returned int>]
20     print([obj.result() for obj in l])
21     print(time.time()-start)
22 # 结果:
23 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
24 6.206435441970825
进程池
 1 # 线程池
 2 from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
 3 import threading
 4 import os,time,random
 5 def task(n):
 6     print('%s:%s is running' %(threading.currentThread().getName(),os.getpid()))
 7     time.sleep(2)
 8     return n**2
 9 
10 if __name__ == '__main__':
11     p=ThreadPoolExecutor()
12     l=[]
13     start=time.time()
14     for i in range(10):
15         obj=p.submit(task,i)
16         l.append(obj)
17     p.shutdown()
18     print('='*30)
19     print([obj.result() for obj in l])
20     print(time.time()-start)
21 
22 # 结果:
23 ==============================
24 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
25 2.0046041011810303
线程池

  进程池 默认个数是CPU个数,而线程池的默认个数是CPU个数的5倍

补充:回调函数

 1 from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
 2 import requests
 3 import os
 4 import time
 5 from threading import currentThread
 6 def get_page(url):
 7     print('%s:<%s> is getting [%s]' %(currentThread().getName(),os.getpid(),url))
 8     response=requests.get(url)
 9     time.sleep(2)
10     return {'url':url,'text':response.text}
11 def parse_page(res):
12     res=res.result()     #与Pool不同之处,这里的res得到的是对象,需要result一下
13     print('%s:<%s> parse [%s]' %(currentThread().getName(),os.getpid(),res['url']))
14     with open('db.txt','a') as f:
15         parse_res='url:%s size:%s
' %(res['url'],len(res['text']))
16         f.write(parse_res)
17 if __name__ == '__main__':
18     # p=ProcessPoolExecutor()
19     p=ThreadPoolExecutor()
20     urls = [
21         'https://www.baidu.com',
22         'https://www.baidu.com',
23         'https://www.baidu.com',
24         'https://www.baidu.com',
25         'https://www.baidu.com',
26         'https://www.baidu.com',
27     ]
28 
29     for url in urls:
30         # multiprocessing.pool_obj.apply_async(get_page,args=(url,),callback=parse_page)
31         p.submit(get_page, url).add_done_callback(parse_page)
32     p.shutdown()
33     print('',os.getpid())
View Code

  3. map方法

 1 from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
 2 import os,time,random
 3 def task(n):
 4     print('%s is running' %os.getpid())
 5     time.sleep(2)
 6     return n**2
 7 
 8 if __name__ == '__main__':
 9     p=ProcessPoolExecutor()
10     obj=p.map(task,range(10))
11     p.shutdown()
12     print('='*30)
13     print(list(obj))
View Code

3.补充:

单线程下串行十个任务效率不一定低,如果是计算型任务,效率不会低

同步异步指的是提交任务的方式

同步:提交任务(纯计算任务)后在原地等着  并不是阻塞。              等待不一定是发生了阻塞:计算时间过长也会等

因为gil锁,python的一个进程的多个线程不能实现并行,但是可以实现并发

如果你开的线程个数在机器的承受范围之内,开线程效率高,如果不行就需要用线程池

函数实现的协程:yield

单线程中提高效率:看情况再说协程,如果是计算型任务你开协程来回的切,反而降低了效率

协程不是真的存在

单线程不可能同时并行两个任务,但是可以出现并发效果
原文地址:https://www.cnblogs.com/liuwei0824/p/7459200.html