【问题标题】:Processes in Python 3.9 exiting with code 1 when It's created inside a ThreadPoolExecutorPython 3.9 中的进程在 ThreadPoolExecutor 中创建时以代码 1 退出
【发布时间】:2023-03-20 09:20:01
【问题描述】:

我有一段代码将任务提交给ThreadPoolExecutor,它启动Process。我已经意识到在 Python 3.8 中 Process 以退出代码 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

注意,如果在 ThreadPoolExecutor 之外调用 __execute_error,它会正常工作。我失踪了吗?这是 Python 3.9 的错误吗?有什么解决方法吗?任何形式的帮助将不胜感激

【问题讨论】:

  • 有趣的发现。我可以确认 3.8/3.9 的差异。另外,ProcessPoolExecutor 似乎总是按预期返回 0,只有 ThreadPoolExecutor 受到影响。
  • 我已经向 Python 问题跟踪器提交了一个同名问题
  • 这很尴尬!您能否留下您为后代发布的问题的链接?
  • 是的,抱歉!我在没有链接的手机上发表了评论。这是:bugs.python.org/issue43944

标签: python-3.x python-multiprocessing python-3.8 python-3.9


【解决方案1】:

multiprocessing 模块提供了 3 种启动进程的方法:spawnforkforkserver。我的猜测是您使用的是基于 Unix 的系统,该系统默认为 fork 方法。 fork 的文档提到:

请注意,安全地分叉多线程进程是有问题的

  • fork 复制调用站点上遇到上述问题的整个过程。
  • spawn 从头开始​​创建一个新的 Python 进程并将所需的资源传递给它。
  • forkserver 创建一个单线程服务器进程,该进程将用作模板来派生未来的进程。因为它是单线程的,所以这个 fork 是安全的。

根据我的测试和描述,选择spawnforkserver 应该适合您并导致exitcode 0

from multiprocessing import Process, set_start_method
set_start_method('spawn')

然而,fork 方法从 Python 3.8 到 3.9 的回归让我担心,所以我将 a comment 留在了 Python 错误跟踪器上。也许有人会解决这个问题,但正如我所说,就文档而言,不支持分叉多线程进程。

【讨论】:

  • 酷!感谢您的回答。我也提交了一个问题:bugs.python.org/issue43944。在我关闭这个问题之前,我会等待官方社区的答复
猜你喜欢
  • 2019-03-15
  • 2019-03-29
  • 2017-09-24
  • 2016-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-03
  • 2020-10-14
相关资源
最近更新 更多