Python 3.9 中的进程在 ThreadPoolExecutor 内创建时以代码 1 退出

问题描述 投票:0回答:1

我有一段代码,将任务提交给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 的错误吗?有什么解决方法吗?任何形式的帮助将非常感激

python python-3.x python-multiprocessing python-3.8 python-3.9
1个回答
1
投票

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错误跟踪器上留下了
评论。也许有人会解决这个问题,但正如我所说,就文档而言,不支持分叉多线程进程。

© www.soinside.com 2019 - 2024. All rights reserved.