带有maxtasksperchild = 1的python3 multiprocessing.Pool不会终止

时间:2019-03-05 10:13:10

标签: python-3.x multiprocessing

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

问题似乎与回调函数的确切功能有关。文档point out that the callback "should return immediately",因为它将阻止管理该池的其他线程。

在我的计算机上重现此行为的一个最小示例如下:(在它不会永远阻塞时,进行一些尝试或增加任务数。)

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()do_stuff都被调用了100次,最后一行中的cb也会永远阻塞。

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

  1. 是否在任何print()回调函数中禁止multiprocessing.Pool? (如何替换该功能?什么是“立即返回”,什么不是?)
  2. 如果是,是否应该更新python文档以使其更清楚?
  3. 如果是,依靠“快速”执行python线程是否是一种好的python做法?这是否违反了不应该对线程的执行顺序进行假设的规则?
  4. 我应该将此报告给python bug跟踪器吗?

0 个答案:

没有答案