1.concurrent.futures模块 直接内置就是 异步的提交 ,如果你想同步也可以实现(p.submit(task,i).result()即同步执行)
2.属性和方法:
1.submit 提交
2.shutdown 关闭池的入口 等池运行结束
#进程池
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
import os,time,random
def task(n):
print('%s is running' %os.getpid())
time.sleep(2)
return n**2 if __name__ == '__main__':
p=ProcessPoolExecutor()
l=[]
start=time.time()
for i in range(10):
obj=p.submit(task,i)
l.append(obj)
p.shutdown()
print('='*30)
# print([obj for obj in l]) # 结果 都是 future 的对象 [<Future at 0x1461d97d1d0 state=finished returned int>,
# <Future at 0x1461d9c6438 state=finished returned int>]
print([obj.result() for obj in l])
print(time.time()-start)
# 结果:
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
6.206435441970825
进程池
# 线程池
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
import threading
import os,time,random
def task(n):
print('%s:%s is running' %(threading.currentThread().getName(),os.getpid()))
time.sleep(2)
return n**2 if __name__ == '__main__':
p=ThreadPoolExecutor()
l=[]
start=time.time()
for i in range(10):
obj=p.submit(task,i)
l.append(obj)
p.shutdown()
print('='*30)
print([obj.result() for obj in l])
print(time.time()-start) # 结果:
==============================
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
2.0046041011810303
线程池
进程池 默认个数是CPU个数,而线程池的默认个数是CPU个数的5倍
补充:回调函数
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
import requests
import os
import time
from threading import currentThread
def get_page(url):
print('%s:<%s> is getting [%s]' %(currentThread().getName(),os.getpid(),url))
response=requests.get(url)
time.sleep(2)
return {'url':url,'text':response.text}
def parse_page(res):
res=res.result() #与Pool不同之处,这里的res得到的是对象,需要result一下
print('%s:<%s> parse [%s]' %(currentThread().getName(),os.getpid(),res['url']))
with open('db.txt','a') as f:
parse_res='url:%s size:%s\n' %(res['url'],len(res['text']))
f.write(parse_res)
if __name__ == '__main__':
# p=ProcessPoolExecutor()
p=ThreadPoolExecutor()
urls = [
'https://www.baidu.com',
'https://www.baidu.com',
'https://www.baidu.com',
'https://www.baidu.com',
'https://www.baidu.com',
'https://www.baidu.com',
] for url in urls:
# multiprocessing.pool_obj.apply_async(get_page,args=(url,),callback=parse_page)
p.submit(get_page, url).add_done_callback(parse_page)
p.shutdown()
print('主',os.getpid())
3. map方法
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
import os,time,random
def task(n):
print('%s is running' %os.getpid())
time.sleep(2)
return n**2 if __name__ == '__main__':
p=ProcessPoolExecutor()
obj=p.map(task,range(10))
p.shutdown()
print('='*30)
print(list(obj))
3.补充:
单线程下串行十个任务效率不一定低,如果是计算型任务,效率不会低 同步异步指的是提交任务的方式 同步:提交任务(纯计算任务)后在原地等着 并不是阻塞。 等待不一定是发生了阻塞:计算时间过长也会等 因为gil锁,python的一个进程的多个线程不能实现并行,但是可以实现并发 如果你开的线程个数在机器的承受范围之内,开线程效率高,如果不行就需要用线程池 函数实现的协程:yield 单线程中提高效率:看情况再说协程,如果是计算型任务你开协程来回的切,反而降低了效率 协程不是真的存在 单线程不可能同时并行两个任务,但是可以出现并发效果