python-3.x - 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()
也花费了“太长时间”?文档的编写方式表明,性能和效率需要非阻塞回调函数,并且不清楚“慢”回调函数会完全破坏池。
- 在任何回调函数中都被
print()
禁止?multiprocessing.Pool
(如何替换那个功能?什么是“立即返回”,什么不是?) - 如果是,是否应该更新 python 文档以明确这一点?
- 如果是,那么依赖 Python 线程的“快速”执行是一种好的 Python 实践吗?这是否违反了不应对线程的执行顺序做出假设的规则?
- 我应该将此报告给 python 错误跟踪器吗?
解决方案
推荐阅读
- django - 如何在 django 中创建允许无限子模型的模型?
- alloy - 如何使用 CompUtil 解析插件
- python - Conda 命令(即:conda env list、sypder、jupyter lab)在“conda update conda”之后不再工作
- powershell - PowerShell FTPS csv文件
- android - 我的应用程序名称未显示在活动之上。显示“com.example.(appname).(file name)
- java - 无法调整 JInternalFrame 的大小
- django - 在 Django 的同一页面上显示项目列表,包括项目详细信息
- android - Gradle 同步失败:无法创建父目录 - Android Studio
- sas - 为什么我收到语法错误 22-322 和错误 76-322
- javascript - TypeScript:元素隐含地具有 RegExp 的“任何”类型