多进程系列之Pool类

254 阅读4分钟

Pool类可以提供指定数量的进程,供用户来调用。当有新的请求提交到Pool中时,若池还没有满,将创建一个新的进程用于执行该请求。反之则该请求就会处于等待状态,直到池中有进程结束。

1.基本介绍

1.1 构造方法

Pool(processes=None, initializer=None, initargs=(),
                 maxtasksperchild=None, context=None)

processes:要创建的进程数,默认使用cpu_count()返回的数量

initializer:每个工作进程启动时要执行的可调用对象,默认为None。如果initializer是None,那么每一个工作进程在开始的时候都会调用initializer(*initargs)

initargs:传递给initializer的参数组

maxtasksperchild:工作进程退出前可以完成的任务数,完成后用一个新的工作进程代替原进程,使得闲置的资源被释放。默认值为None,表示Pool中只要存在工作进程就会一直存活。

context:用于制定工作进程启动时的上下文,一般使用Pool()或者context对象的Pool()方法来创建一个池,两种方法都设置了context

1.2 实例方法

apply(func[,args[,kwargs]]):在一个池的工作进程中执行func(*args, **kwargs)返回结果。这里注意的一点是该操作不会在池的所有工作进程中执行func函数。如果需要通过不同的参数来并发执行func函数,必须同不同线程调用apply()函数或者使用apply_saync()函数来完成该操作。该方法是阻塞的。

apply_saync(func[,args[,kwargs={}[,callback=None]]]):在一个池的工作进程中执行func(*args, **kwargs)返回结果。此方法的结果是AsyncResult类的实例,callback是可调用对象,接收输入参数。当func结果变为可用时,将传递给callback。callback禁止执行任何阻塞操作,否则将接收其他异步操作的结果。它是非阻塞的。

map(func,iterable[,chunksize=None]):Pool类中的map方法,与内置的map函数用法行为基本一致,它会使进程阻塞直到返回结果。虽然第二个参数iterable是一个迭代器,但是必须等整个队列都就绪准备好以后,才可以运行子进程。

map_saync(func,iterable[,chunksize=None]):与map()的关系类似于apply_saync()与apply()

imap():imap与map的区别在于map必须等所有的进程都执行完才会返回结果,imap则是立刻返回结果。

imap_unorderes():不保证返回的结果顺序与进程添加的顺序一致。

colse():关闭进程池,防止进一步操作。如果所有操作持续挂起,它们将在工作进程终止前完成。

join():等待所有工作进程退出。此方法只能在colse()或者terminate()之后调用,让其不再接收新的Process

terminate():结束工作进程,不再处理未处理的任务

1.3 AsyncResult类的实例方法

apply_saync()方法与map_saync()方法的返回值是AsyncResult类的实例。该实例具有以下几个方法

get():返回结果,如果有必要则等待结果到达。timeout可选,若在指定时间内没有到达则引发异常。

ready():如果调用完成,返回True。

successful():如果调用完成且没有引发异常,则返回True。如果在结果就绪之前调用该方法,则引发异常。

wait(timeout):等待结果变为可用

terminate():立即终止所有工作进程,同时不清理或结束任何挂起工作。如果进程被垃圾回收,则自动调用此函数。

2.使用实例

2.1 apply实例

from multiprocessing import Pool
​
​
def test_task(i):
    print(i)
​
​
if __name__ == '__main__':
    pool = Pool(2)
    for i in range(10):
        pool.apply(test_task, args=(i,))
    print('end')
    pool.close()
    pool.join()

result:

0
1
2
3
4
5
6
7
8
9
end

由于apply()方法是阻塞的,所以按照顺序执行,整个进程结束后才会执行 print('end')语句

2.2 apply_async实例二

from multiprocessing import Pool
​
​
def test_task(i):
    print(i)
​
​
if __name__ == '__main__':
    pool = Pool(2)
    for i in range(10):
        pool.apply_async(test_task, args=(i,))
    print('end')
    pool.close()
    pool.join()

result:

end
0
1
2
3
4
5
6
7
8
9

由于apply_async()为非阻塞的,所以print('end')语句的执行顺序在进程启动循环的前面

2.3 map实例

from multiprocessing import Pool
​
​
def test_task(i):
    print(i)
​
​
if __name__ == '__main__':
    list1 = range(10)
    pool = Pool(2)
    pool.map(test_task, list1)
    print('end')
    pool.close()
    pool.join()

result:

0
1
2
3
4
5
6
7
8
9
end