八、进程池

进程池(掌握)

一、进程池Pool

当需要创建的子进程数量不多时,可以直接利用multiprocessing中的Process动态生成多个进程,但是如果是上百升值上千个目标,手动的去创建进程的工作量巨大,此时就可以用到multiprocessing模块提供的Pool方法

初始化Pool时,可以指定一个最大进程数,当有新的请求提交到Pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但是如果池中的进程数已经达到指定的最大值,那么该请求就会等待,直到池中有进程结束,才会用之前的进程来执行新的任务,请看以下实例:

  1. 语法:
from multiprocessing import Process


# 创建进程池
p = Pool([numprocess  [,initializer [, initargs]]])

'''
参数介绍:
	numprocess:要创建的进程数,如果省略,将默认使用cpu_count()的值,即CPU的内核数
	initializer:是每个工作进程启动时要执行的可调用对象,默认为None
	initargs:是要传给initializer的参数组
'''

1、主要方法

1.1 apply()

  1. 语法:
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类

  1. 语法:
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 来代表。

  1. 语法:
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() 方法后的进程池不再接收新任务,但会将以前所有的已提交任务执行完成。当进程池中的所有任务都执行完成后,该进程池中的所有进程都会死亡。

  1. 语法:
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 处理。
posted @ 2021-06-04 14:13  zzwYYYYYY  阅读(169)  评论(0)    收藏  举报