文章目录
- Python multiprocessing进程池使用详解
- 1. 进程池使用场景
- 2. 常用函数详解
- 2.1 Pool
- 2.2 apply(func[, args[, kwds]])
- 2.3 apply_async(func[, args[, kwds[, callback[, error_callback]]]])
- 2.4 starmap(func, iterable[, chunksize])
- 2.5 startmap_async(func, iterable[, chunksize[, callback[, error_callback]]])
- 2.6 map(func, iterable[, chunksize])
- 2.7 map_async(func, iterable[, chunksize[, callback[, error_callback]]])
- 2.8 close()
- 2.9 terminate()
- 2.10 join()
- 2.11 AsyncResult
- 3. 常见问题
Python multiprocessing进程池使用详解
先放官方文档
1. 进程池使用场景
当我们需要执行较大规模的并发任务时,如果每个分片任务都直接创建一个子进程并开始执行,程序很可能会瞬间创建很多子进程造成cpu资源拥挤,导致并行效率低。因此我们需要控制并发任务量,并且集中管理。
2. 常用函数详解
2.1 Pool
推荐方式:
from multiprocessing import Pool
p = Pool(size)
# 向pool下发任务
p.close()
p.join()
这样主进程会等待子进程全部执行完毕之后再退出。
踩坑注意:
with Pool(size) as p:
这种方式with退出后子进程也会退出,无论子进程是否执行完。
官方解释
__enter__() returns the pool object, and __exit__() calls terminate()
即with进入的时候返回pool实例,退出时调用pool.terminate()
例:
子进程未完全执行就随主进程退出而退出了,数据未写入文件。
2.2 apply(func[, args[, kwds]])
不推荐使用,向进程池添加单个任务,子进程会block主进程执行,相当于没有并行
返回值为func返回值
2.3 apply_async(func[, args[, kwds[, callback[, error_callback]]]])
向进程池添加单个任务,非阻塞,使用场景:必须使用关键字参数,或者需要逐个任务添加(任务不同或者任务参数会发生变化等)等。
返回数据类型为multiprocessing.pool.AsyncResult
。
func、callback、error_callback之间关系模型参考:
def apply_async(...):
try:
res = func(*args, **kwargs)
except Exception as e:
error_callback(e) # 不需要函数返回值
else:
callback(res) # 不需要函数返回值
return res
使用样例:
p = Pool(10)
r = [p.apply_async(func, (i,), callback=cb, error_callback=ecb) for i in range(4)]
p.close()
p.join()
r = [res.get() for res in r]
2.4 starmap(func, iterable[, chunksize])
并行执行多个任务,阻塞主进程直至全部返回,可向func传多个位置参数,但不能传关键字参数。
返回值为列表,列表中元素为func依次的返回值。
使用样例:
p = Pool(10)
r = p.startmap(func, [(1, 2, 3), (4, 5, 6)])
print(r)
2.5 startmap_async(func, iterable[, chunksize[, callback[, error_callback]]])
并行执行多个任务,不阻塞主进程,可向func传多个位置参数,但不能传关键字参数。
返回值为List[AsyncResult]
2.6 map(func, iterable[, chunksize])
startmap
简化版,限制func只能接受一个位置参数,不推荐使用。
2.7 map_async(func, iterable[, chunksize[, callback[, error_callback]]])
startmap_async
简化版,限制func只能接受一个位置参数,不推荐使用。
2.8 close()
防止更多任务加入进程池,全部任务结束后所有进程退出。
2.9 terminate()
立即停止所有子进程即使进程任务未结束,当gc回收进程池时会立即调用。
2.10 join()
等待所有子进程退出,调用前必须先调用close()
或者terminate()
2.11 AsyncResult
支持get([timeout]), wait([timeout]), ready(), successful()
四个方法,get使用可参考上文样例,其他详见官方文档。
3. 常见问题
3.1 子进程未执行就退出
可能原因:
- 使用了with,with退出自动结束子进程,详情参考上文2.1
- 子进程无法获取到某些变量,因为子进程无法访问到主进程内存。常见一些无法pickle的数据结构,或是作用域外的变量