八、进程池
进程池(掌握)
一、进程池Pool
当需要创建的子进程数量不多时,可以直接利用multiprocessing中的Process动态生成多个进程,但是如果是上百升值上千个目标,手动的去创建进程的工作量巨大,此时就可以用到multiprocessing模块提供的Pool方法
初始化Pool时,可以指定一个最大进程数,当有新的请求提交到Pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但是如果池中的进程数已经达到指定的最大值,那么该请求就会等待,直到池中有进程结束,才会用之前的进程来执行新的任务,请看以下实例:
- 语法:
from multiprocessing import Process
# 创建进程池
p = Pool([numprocess [,initializer [, initargs]]])
'''
参数介绍:
numprocess:要创建的进程数,如果省略,将默认使用cpu_count()的值,即CPU的内核数
initializer:是每个工作进程启动时要执行的可调用对象,默认为None
initargs:是要传给initializer的参数组
'''
1、主要方法
1.1 apply()
- 语法:
from threading import Pool
# 创建一个进程池
p = Pool(3)
p.apply(func [, args [, kwargs]])
'''
参数介绍:
func:函数名,在一个池工作进程中需要执行的函数
args:传递给func函数的参数,为元组数据类型
(实参1,实参2...)
kwargs:传递给func函数的命名参数,以字典的数据类型
{'参数1':'参数值1','参数2':'参数值2',...}
'''
在一个池工作进程中执行func(*args,**kwargs),然后返回结果。需要强调的是:此操作并不会在所有池工作进程中并执行func函数。如果要通过不同参数并发地执行func函数,必须从不同线程调用p.apply()函数或者使用p.apply_async()
1.2 apply_async()
from threading import Pool
# 创建一个进程池
p = Pool(3)
apply_async(func [, args [, kwargs]])
'''
参数介绍:
func:函数名,在一个池工作进程中需要执行的函数
args:传递给func函数的参数,为元组数据类型
(实参1,实参2...)
kwargs:传递给func函数的命名参数,以字典的数据类型
{'参数1':'参数值1','参数2':'参数值2',...}
'''
在一个池工作进程中执行func(*args,**kwargs),然后返回结果。此方法的结果是AsyncResult类的实例,callback是可调用对象,接收输入参数。当func的结果变为可用时,将理解传递给callback。callback禁止执行任何阻塞操作,否则将接收其他异步操作中的结果。
1.3 join()
jion():原地阻塞并等待所有工作进程退出。此方法只能在close()或teminate()之后调用
1.4 close()
close():关闭进程池,防止进一步操作。如果所有操作持续挂起,它们将在工作进程终止前完成
2、其他方法
'''
方法apply_async()和map_async()的返回值是AsyncResul的实例obj。实例具有以下方法
obj.get():返回结果,如果有必要则等待结果到达。timeout是可选的。如果在指定时间内还没有到达,将引发一场。如果远程操作中引发了异常,它将在调用此方法时再次被引发。
obj.ready():如果调用完成,返回True
obj.successful():如果调用完成且没有引发异常,返回True,如果在结果就绪之前调用此方法,引发异常
obj.wait([timeout]):等待结果变为可用。
obj.terminate():立即终止所有工作进程,同时不执行任何清理或结束任何挂起工作。如果p被垃圾回收,将自动调用此函数
二、Future类
进程池的基类是 concurrent.futures 模块中的 Executor,Executor 提供了两个子类,即 ThreadPoolExecutor 和 ProcessPoolExecutor,其中 ThreadPoolExecutor 用于创建线程池,而 ProcessPoolExecutor 用于创建进程池。
'''
Future 提供了如下方法,线程进程通用:
cancel():取消该 Future 代表的线程任务。如果该任务正在执行,不可取消,则该方法返回 False;否则,程序会取消该任务,并返回 True。
cancelled():返回 Future 代表的线程任务是否被成功取消。
running():如果该 Future 代表的线程任务正在执行、不可被取消,该方法返回 True。
done():如果该 Funture 代表的线程任务被成功取消或执行完成,则该方法返回 True。
result(timeout=None):获取该 Future 代表的线程任务最后返回的结果。如果 Future 代表的线程任务还未完成,该方法将会阻塞当前线程,其中 timeout 参数指定最多阻塞多少秒。
exception(timeout=None):获取该 Future 代表的线程任务所引发的异常。如果该任务成功完成,没有异常,则该方法返回 None。
add_done_callback(fn):为该 Future 代表的线程任务注册一个“回调函数”,当该任务成功完成时,程序会自动触发该 fn 函数。
调用该方法会自动将该线程的Future对象作为参数传递给fn,fn可以在内部使用Future的方法从而获取该线程的信息
'''
1、ProcessPoolExecutor类
- 语法:
from concurrent.futures import ProcessPoolExecutor
pool = ProcessPoolExecutor(max_workers=None, mp_context=None,initializer=None, initargs=())
'''
参数介绍:
max_workers:设置进程池可容纳的最大线程数
默认值:CPU内核数
int:也可以输入一个int类型的数值,指定最大进程数
mp_context:
initializer:是每个工作进程启动时要执行的可调用对象,默认为None,即每次使用pool.submit()方法时
initargs:是要传给initializer的参数组
(实参1,实参2...)
'''
1.1 submit()
向进程池中提交任务(函数),是异步操作
程序将 task 函数提交(submit)给进程池后,submit 方法会返回一个 Future 对象,Future 类主要用于获取线程任务函数的返回值。由于进程任务会在新进程中以异步方式执行,因此,线程执行的函数相当于一个“将来完成”的任务,所以 Python 使用 Future 来代表。
- 语法:
from concurrent.futures import ProcessPoolExecutor
pool = ProcessPoolExecutor(max_workers=None, mp_context=None,initializer=None, initargs=())
def zzw():
pass
pool.submit(fn, *args, **kwargs)
'''
参数介绍:
fn:创建进程时,需要执行的代码,由函数封装
*args:参数1, 参数2,...:传入func函数的参数
**kwargs:传入fn的可变参数
a = 11, b = 22
返回值:
返回一个_base.Future类
<class 'concurrent.futures._base.Future'>
Future类中的方法:
result():获取submit(fn)提交任务的返回结果,即fn函数的return值,并且在该子进程输出返回结果时,主进程阻塞
'''
1.2 shutdown()
关闭进程池,并原地阻塞等待进程池中所有的任务执行完毕
在用完一个进程池后,应该调用该进程池的 shutdown() 方法,该方法将启动进程池的关闭序列。调用 shutdown() 方法后的进程池不再接收新任务,但会将以前所有的已提交任务执行完成。当进程池中的所有任务都执行完成后,该进程池中的所有进程都会死亡。
- 语法:
from concurrent.futures import ProcessPoolExecutor
pool = ProcessPoolExecutor(max_workers=None, mp_context=None,initializer=None, initargs=())
pool.shutdown(wait=True)
1.3 map()-了解
map(func, *iterables, timeout=None, chunksize=1):该函数类似于全局函数 map(func, *iterables),只是该函数将会启动多个线程,以异步方式立即对 iterables 执行 map 处理。

浙公网安备 33010602011771号