我有一段代码,将任务提交给ThreadPoolExecutor,它启动一个Process。我意识到在 Python 3.8 中,进程以退出代码
0
结束。但我已经将 Python 更新到了 3.9 版本,并且开始以退出代码 1
结束!即使进程执行空任务。
这是一个最小的例子:
from multiprocessing import Process
from concurrent.futures import ThreadPoolExecutor
def some_task():
pass
def execute_error():
p = Process(target=some_task)
p.start()
p.join()
print(p.exitcode) # This is always 1 on a ThreadPoolExecutor!!!
executor = ThreadPoolExecutor(max_workers=4)
executor.submit(execute_error)
# execute_error() # IMPORTANT: this works correctly (exit 0)
我的版本:
Ubuntu 21.04
Python 3.9.4
注意,如果
__execute_error
在 ThreadPoolExecutor 之外调用,它可以正常工作。难道还有我失踪吗?这是 Python 3.9 的错误吗?有什么解决方法吗?任何形式的帮助将非常感激
multiprocessing
模块提供了3种启动进程的方法:spawn
、fork
和forkserver
。我的猜测是您使用的是基于 Unix 的系统,默认使用 fork
方法。 fork
的文档提到:
请注意,安全地分叉多线程进程是有问题的。
fork
在调用站点复制整个流程,遇到上述问题。spawn
从头开始创建一个新的 Python 进程并将所需的资源传递给它。forkserver
创建一个单线程服务器进程,该进程将用作派生未来进程的模板。由于它是单线程的,所以这个 fork 是安全的。根据我的测试和描述,选择
spawn
或 forkserver
应该适合您并导致 exitcode
0。
from multiprocessing import Process, set_start_method
set_start_method('spawn')
然而,fork
方法从Python 3.8到3.9的回归让我担心,所以我在Python错误跟踪器上留下了评论。也许有人会解决这个问题,但正如我所说,就文档而言,不支持分叉多线程进程。