1.concurrent.futures模块 直接内置就是 异步的提交 ,如果你想同步也可以实现(p.submit(task,i).result()即同步执行)
2.属性和方法:
1.submit 提交
2.shutdown 关闭池的入口 等池运行结束
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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倍
补充:回调函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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())
3. map方法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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))
3.补充:
单线程下串行十个任务效率不一定低,如果是计算型任务,效率不会低 同步异步指的是提交任务的方式 同步:提交任务(纯计算任务)后在原地等着 并不是阻塞。 等待不一定是发生了阻塞:计算时间过长也会等 因为gil锁,python的一个进程的多个线程不能实现并行,但是可以实现并发 如果你开的线程个数在机器的承受范围之内,开线程效率高,如果不行就需要用线程池 函数实现的协程:yield 单线程中提高效率:看情况再说协程,如果是计算型任务你开协程来回的切,反而降低了效率 协程不是真的存在
单线程不可能同时并行两个任务,但是可以出现并发效果