一、为什么要有进程池
开启过多的进程并不能提高你的效率,反而会降低效率。
1.1 计算密集型
充分占用CPU 多进程可以充分利用多核。适合开启多进程,但是不适合开启很多多进程。
1.2 IO密集型
大部分时间都在阻塞对列中,而不是在运行状态中
根本不太适合开启多进程
简单进程池的代码实现 ---->异步提交
from multiprocessing import Pool def func(num): print('做了第%s间衣服'%num) if __name__ == '__main__': p = Pool(4) for i in range(10): p.apply_async(func,args=(i,)) # 异步提交func到一个子进程中执行 p.close() # 关闭进程池,用户不能再向这个池中提交任务了 p.join() # 阻塞,直到进程池中所有的任务都被执行完
简单进程池的代码实现 ---->同步提交
from multiprocessing import Pool def task(num): time.sleep(1) print('%s:%s'%(num,os.getpid())) return num**2 if __name__ == '__main__': p = Pool(4) for i in range(20): res = p.apply(task,args=(i,)) # 提交任务的方法 同步提交 print('-->',res) # 同步提交,有返回值
进程池---->异步提交,有返回值 # 通过 get()方法实现
from multiprocessing import Pool def task(num): time.sleep(1) print('%s:%s'%(num,os.getpid())) return num**2 if __name__ == '__main__': p = Pool() res_lst = [] for i in range(20): res = p.apply_async(task,args=(i,)) # 提交任务的方法 异步 提交 res_lst.append(res) # 对象(编号) for res in res_lst: print('-->',res.get())
实例化 传参数 进程的个数 cpu/cpu + 1
提交任务
同步提交 apply
返回值:子进程对应函数的返回值
一个一个顺序执行的,并没有任何并发效果
异步提交 apply_async
没有返回值,要想所有任务能够顺利的执行完毕
p.close()
p,join() # 必须先close再join,阻塞直到进程池中的所有任务都执行完毕
有返回值的情况下
res.get() # get不能再提交任务之后立刻执行,应该是先提交所有的任务再通过get获取结果
map()方法
import os import time from multiprocessing import Pool def task(num): time.sleep(1) print('%s:%s'%(num,os.getpid())) return num**2 if __name__ == '__main__': p = Pool() p.map(task,range(20))
map()方法
异步提交的简化版本
自带close和join方法
回调函数
1、使用主进程统一获取结果,这样的话在主进程之间没有数据隔离
2、多个子进程所做的事情是比较长时间的,而主进程中一般情况下回调函数的执行速度都不较快
子进程中做网络访问、数据分析
拿着访问结果 或者 数据分析结果 来做一些汇总工作
3、 子进程去访问网页,主进程处理网页的结果
4、 子进程有大量的计算要去做,主进程等待结果做简单的处理
实例代码:回调函数
from multiprocessing import Pool def func(i): print('第一个任务') return '*'*i def call_back(res): print(res) if __name__ == '__main__': p = Pool() p.apply_async(func,args=(1,),callback=call_back) p.close() p.join() 结果为: 第一个任务 *
回调函数特点:
1、当func执行完毕之后执行callback函数
2、func的返回值会作为callback的参数
3、回调函数是哪个进程实现的??主进程