首页 > 解决方案 > python3 multiprocessing.Pool with maxtasksperchild=1 不会终止

问题描述

multiprocessing.Pool在 python 3.6 或 3.7 with 中使用时maxtasksperchild=1,我注意到池产生的一些进程挂起并且不会退出,即使它们的任务的回调已经执行。结果,Pool.join()将永远阻塞,即使所有任务都已完成。在进程树中,可以看到正在运行但处于空闲状态的子进程。如果maxtasksperchild=None.

问题似乎与回调的确切作用有关。文档指出回调“应该立即返回”,因为它会阻塞管理池的其他线程。

在我的机器上重现此行为的最小示例如下:(尝试几次或在它不会永远阻塞时增加任务数。)

from multiprocessing import Pool
from os import getpid
from random import random
from time import sleep


def do_stuff():
    pass


def cb(arg):
    sleep(random())  # can be replaced with print('foo')


p = Pool(maxtasksperchild=1)
number_of_tasks = 100  # a value may depend on your machine -- for mine 20 is sufficient to trigger the behavior
for i in range(number_of_tasks):
    p.apply_async(do_stuff, callback=cb)


p.close()
print("joining ... (this should take just seconds)")
print("use the following command to watch the process tree:")
print("    watch -n .2 pstree -at -p %i" % getpid())
p.join()

与我的预期相反,p.join()即使最后一行都被调用了 100 次,最后一行也会永远do_stuff阻塞cb

我知道这sleep(random())违反了文档,但print()也花费了“太长时间”?文档的编写方式表明,性能和效率需要非阻塞回调函数,并且不清楚“慢”回调函数会完全破坏池。

  1. 在任何回调函数中都被print()禁止?multiprocessing.Pool(如何替换那个功能?什么是“立即返回”,什么不是?)
  2. 如果是,是否应该更新 python 文档以明确这一点?
  3. 如果是,那么依赖 Python 线程的“快速”执行是一种好的 Python 实践吗?这是否违反了不应对线程的执行顺序做出假设的规则?
  4. 我应该将此报告给 python 错误跟踪器吗?

标签: python-3.xmultiprocessing

解决方案


推荐阅读