1、multiprocess模块详解
Python的os模块封装了常见的系统调用,其中就包含 「fork函数」,通过这个函数可以轻松的创建子进程,但是要注意一点,在Windows系统上是无法使用fork函数的,Python为我们提供了可跨平台的multiprocess模块。该模块提供了一个Process类来代表一个进程对象,用法和Thread非常相似。
① Process进程对象
创建一个进程的代码示例如下:
from multiprocessing import Process import os def show_msg(name): print("子进程运行中:name = %s , pid = %d " % (name, os.getpid())) if __name__ == '__main__': print("父进程 %d" % os.getpid()) p = Process(target=show_msg, args=('测试',)) print("开始执行子进程~") p.start() p.join() print("子进程执行完毕!")
运行结果如下:
父进程 26539 开始执行子进程~ 子进程运行中:name = 测试 , pid = 26540 子进程执行完毕!
Process构造函数:
Process(group=None, target=None, name=None, args=(), kwargs={})
参数详解:
- group:分组,很少用到
- target:调用对象,传入任务执行函数作为参数
- name:进程别名
- args:给调用对象以元组的形式提供参数,比如有两个参数args=(a,b),如果只有一个参数,要这样写args=(a,),不能把逗号漏掉,不然会被当做括号运算符使用!
- kwargs:调用对象的关键字参数字典
Process的常用函数:
- is_alive():判断进程实例是否还在执行;
- join([timeout]):是否等待进程实例执行结束,或等待多少秒;
- start():启动进程实例(创建子进程);
- run():如果没有给定target参数,对这个对象调用start()方法时,
就将执行对象中的run()方法;
- terminate():不管任务是否完成,立即终止;
除了使用fork函数和上述操作创建进程的方式外,还可以自定义一个Process类,重写__init__
和run函数
即可,代码示例如下:
from multiprocessing import Process import os class MyProcess(Process): def __init__(self, name): Process.__init__(self) self.msg = name def run(self): print("子进程运行中:name = %s , pid = %d " % (self.msg, os.getpid())) if __name__ == '__main__': print("父进程 %d" % os.getpid()) p = MyProcess('测试') print("开始执行子进程~") p.start() p.join() print("子进程执行完毕!")
运行结果如下:
父进程 26794 开始执行子进程~ 子进程运行中:name = 测试 , pid = 26795 子进程执行完毕!
② Pool进程池
知道了如何创建进程,那么实现多进程有不是什么难事了,一个循环创建多个即可,但是有个问题,进程可是重量级别的程序,重复进程创建和销毁会造成一定的性能开销! Python为我们提供了一个进程池对象Pool用来缓解进程重复关启带来的性能消耗问题。在创建进程池的时候指定一个容量,如果接收到一个新任务,而池没满的话,会创建一个新的进程来执行这个任务,如果池满的话,任务则会进入等待状态,直到池中有进程结束,才会创建新的进程来执行这个任务。
Pool的构造函数:
Pool(processes=None, initializer=None, initargs=(),maxtasksperchild=None, context=None)
一般只用到第一个参数,processes用于设置进程池的容量,即最多并发的进程数量,如果不写默认使用os.cpu_count()
返回的值。
Pool常用函数详解:
- apply(func, args=(), kwds={}):使用堵塞方式调用func,堵塞的意思是一个进程结束,释放回进程池,下一个进程才可以开始,args为传递给func的参数列表,kwds为传递给func的关键字参数列表,该方法在Python 2.3后就不建议使用了。
- apply_async(func, args=(), kwds={}, callback=None,error_callback=None) :使用非阻塞方式调用func,进程池进程最大数可以同时执行,还支持返回结果后进行回调。
- close():关闭进程池,使其不再接受新的任务;
- terminate():结束工作进程,不再处理未处理的任务,不管任务是否完成,立即终止;
- join():主进程阻塞,等待⼦进程的退出,必须在close或terminate之后使用;
- map(func, iterable, chunksize=None):这里的map函数和Python内置的高阶函数map类似,只是这里的map方法是在进程池多进程并发进行的,接收一个函数和可迭代对象,把函数作用到每个元素,得到一个新的list返回。
最简单的进程池代码示例如下:
import multiprocessing as mp import time def func(msg): time.sleep(1) print(mp.current_process().name + " : " + msg) if __name__ == '__main__': pool = mp.Pool() for i in range(20): msg = "Do Something %d" % (i) pool.apply_async(func, (msg,)) pool.close() pool.join() print("子进程执行任务完毕!")