Python3并发编程之multiprocessing库

文章目录

  • multiprocessing与threading
  • 创建进程时的注意事项
  • Process对象的部分方法及属性
  • 创建进程池对象——threading.Pool()
  • 创建管道对象——threading.Pipe()
  • 创建管理器对象——threading.Managert()
  • 创建栅栏对象——threading.Barrier()

multiprocessing、threading、queue

multiprocessing与threading都是python3的标准库,multiprocessing的类,函数,方法,属性等,与threading库的实现效果大多相同,本篇将因此减少篇幅。可以的话,请移步至《Python3并行编程之threading》。
multiprocessing.Queue()与Python3标准库quue在实现队列的操作上基本一致。不同的是,multiprocessiing中的队列是跨进程存在的,而queue不是,主要使用于多线程模式下;并且它们支持的模块类型也不同,但这并不影响我们学习。如果可以,请移步至《Python3中queue模块》。
本文中提到的主进程阻塞,是指主进程只有一个线程的情况。

创建进程时的注意事项

1、 在multiprocessing库中,守护进程(后台进程)是不具有创建子进程能力的。否则,当守护进程的父进程运行完毕后,守护进程会随之终止,此时,这个进程将成为游离进程。
而threading库不受这种拘束,但不支持。在threading中,守护线程产出的线程,只在主线程结束后结束。
2、 在子进程不为守护进程时,子进程自然结束,该子进程的后代也会一起结束。
3、 使用multiprocessing库创建子进程时,创建的子进程会导入包含目标函数的脚步文件。而在该文件中添加 if __ name __ == ‘__ main __’: 或将目标函数放入一个较为干净的文件夹可以避免该机制引发的错误。在忘记添加此行代码时创建进程,在不加阻拦的情况下,会创建无数个进程。但不用担心,在创建进程之前,该库会检查是否会出现上述情况,并在必要时,引发RuntimeError错误。
该机制并不会在threading模块中出现。

Process对象的方法及属性

描述对象 描述
terminate() 终止进程。该进程的后代不会因此终止,它们将成为游离进程。
pid 返回进程ID。在生成该进程之前,这将是 None 。
exitcode 在启动进程前,该值为None。在启动后,它可能出现三种范围的值:若该值大于零,表示进程遇到了错误并退出;若该值等于零,表示该进程正常运行。若该值小于零,表示进程被用数字表示的终止信号N终止了,此时exitcode=-1*N。

创建进程池对象——mutiprocessing.Pool()

该对象可对进程池中的进程个数进行限制,防止进程创建过多。并且能够对进程池中的对象执行批量化操作,为Python多进程开发带来便利。

Pool类的参数:

参数 描述
processes=None 进程池中的最大进程数。当该参数的默认值为None时,使用os.cpu_count()返回的值作为processes的参数值。
initializer=None 在前Processes个进程执行前执行此参数关联函数(初始化函数),超过个数的进程前不具有此功能。
initargs=() 向初始化函数传参,值是一个元组。
maxtasksperchild 池中的工作进程在退出或被新工作进程替换之前执行目标函数的最大次数。

Pool对象的方法:

方法 描述
apply(func,args=(),kwargs={}) 使用apply向池中添加进程时主进程会发生阻塞,直到前一个池中进程执行完毕,没有则直接添加。也就是说,使用该方法添加进程,在任意时刻进程池中有且只有一个进程。
apply_async(func,args=(),kwargs={},callback,error_callback) 如果指定了 callback , 它 必须 是一个接受单个参数的可调用对象。当执行成功时, callback 会被用于处理执行后的返回结果,否则,调用 error_callback 。如果指定了 error_callback , 它 必须 是一个接受单个参数的可调用对象。当目标函数执行失败时, 会将抛出的异常对象作为参数传递给 error_callback 执行。处理返回信号的函数应该立即执行,否则会阻塞负责线程。
close() 关闭进程池,不允许再向进程池中添加进程,否则将引发ValueError错误。
terminate() 关闭进程池,连同池中进程。
join() 阻塞主进程,直到进程池中进程完成指定任务。

注:
1、进程池对象的方法只能由创建它的进程使用。
2、当池中的进程对象执行的目标函数出现错误时,并不会触发系统错误所引起的中断,执行目标函数的结果并不特殊,与普通代码无异。
3、目前该对象在Windows上的Pycharm上无法正常运行,在命令行环境可正常执行。

创建管道对象——multiprocssing.Pipe()

multiiprocessing.Pipe(duplex=True)返回包含由管道所连接的一对连接对象的列表,这个管道默认是双向的,使用返回的任意一个对象即可完成数据的发送与接收。通过将参数duplex的值设置为False可以实现单向管道,此时返回对象列表的第一个对象仅能接收数据,第二个对象仅能发送数据。
注:
在双向管道的情况下,同时在管道的同一端进行数据的发送与接收,可能会损坏管道中的数据。同时使用管道的两端进行数据收发则不会出现该现象。
Pipe对象的方法:

方法 描述
send(data) 将数据发送至接收端。
recv() 从发送端接收数据并将其作为返回值返回。

创建管理器对象——multiprocessing.Manager()

Manager()类返回一个管理器对象,管理器对象会控制一个服务器端进程,该进程持有一个共享对象,该对象可以被其他进程操作。当有进程修改该对象时,管理器对象会确保共享对象在所有进程中都会更新,但该过程执行缓慢。
Manager() 返回的管理器支持类型: list 、 dict 、 Namespace 、 Lock 、 RLock 、 Semaphore 、 BoundedSemaphore 、 Condition 、 Event 、 Barrier 、 Queue 、 Value 和 Array 。当然,它也支持数据类型嵌套。
示例(创建一个共享列表对象): man_lis_src = Managet.list(data)

创建栅栏对象——multiprcoessing.Barrier()

Barrier()类对象用于应对固定数量的进程需要彼此相互等待的情况。进程调用 wait() 方法后将发生阻塞,直到指定数量的进程都调用了 wait() 方法。条件满足后,这些进程将被同时被释放。
栅栏对象有三种状态,破损态、破碎态和初始态。如果栅栏对象进入破损态,或重置栅栏时仍有进程等待释放,将会触发 BrokenBarrierError 错误。
Barrier类的参数:

参数 描述
party 设置释放指定个数的进程所需的最少调用wait()方法的进程数。
action=None 释放进程前,在调用wait()方法的一组进程中指定一个线程执行action参数所关联的可调用对象。如果此调用触发错误,栅栏将进入破损态。
timeout=None 用于为wait()方法指定默认的超时时间,该值能够被wait()方法中的相同参数所指定的值(排除值为None的情况)覆盖。

Barrier对象的方法及属性:

描述对象 描述
wait(timeout=None) 阻塞进程,直到指定数量进程调用该方法。timeout参数可以设置超时时间,若触发超时,栅栏对象将进入破损态。该方法具有一个整数的返回值,值的范围在 [0,parties - 1],可以使用该方法指定其中的一个进程。
reset() 将栅栏对象重置为初始态。
abort() 调用该方法使栅栏进入破碎态。栅栏进入破碎态后,调用wait()方法都将触发 BrokenBarrierError 错误。
parties 释放指定个数的进程所需的最少调用wait()方法的进程数。
n_waiting 当前被栅栏阻塞的进程个数。
broken 该属性是一个能表示栅栏状态的布尔值,若为True,则说明栅栏现在为破损态。

你可能感兴趣的:(Python3并发编程)