Python 多处理运行时错误

Posted

技术标签:

【中文标题】Python 多处理运行时错误【英文标题】:Python multiprocessing RuntimeError 【发布时间】:2020-09-19 09:53:51 【问题描述】:

我有一个简单的函数,我打算使用 Python 多处理模块并行运行。但是我收到以下错误RuntimeError: An attempt has been made to start a new process before the current process has finished its bootstrapping phase. 该错误表明我添加了这个:

if __name__ == '__main__':
freeze_support()

大多数在线帖子都建议像这样 SO answer。

我添加了它并且它可以工作,但我似乎不明白为什么这么简单的一段代码需要它。

没有 __name__=="__main__" 的代码(抛出 RuntimeError)

import multiprocessing
import time

start = time.perf_counter()


def do_something():
    print('Sleeping 1 second...')
    time.sleep(1)
    print('Done sleeping...')

p1 = multiprocessing.Process(target=do_something)
p2 = multiprocessing.Process(target=do_something)
p1.start()
p2.start()

finish = time.perf_counter()

print(f'Finished in round(finish - start, 2) second(s)')

带有 __name__=="__main__" 的代码(不抛出 RuntimeError)

import multiprocessing
import time

start = time.perf_counter()


def do_something():
  print('Sleeping 1 second...')
  time.sleep(1)
  print('Done sleeping...')


def main():
   p1 = multiprocessing.Process(target=do_something)
   p2 = multiprocessing.Process(target=do_something)
   p1.start()
   p2.start()

   finish = time.perf_counter()
   print(f'Finished in round(finish - start, 2) second(s)')


if __name__ == "__main__":
   main()

【问题讨论】:

你在第一个脚本中有缩进吗? do_something 创建一个调用do_something 等的进程,这会很快爆炸,除非没有对do_something 的***调用,因此不会创建进程。 可能相关:bugs.python.org/issue37205 【参考方案1】:

在 Windows 中,multiprocessing.Process 执行一个新的 python 副本来运行代码。它必须获取您要执行的代码以在该进程中加载​​,以便它挑选当前环境的快照以在子进程中扩展。为此,孩子需要重新导入父母使用的模块。特别是,它需要将主脚本作为模块导入。导入时,驻留在模块级别的任何代码都会执行。

让我们做一个最简单的例子

foo.py

import multiprocessing as mp
process = mp.Process(target=print, args=('foo',))
process.start()
process.join()

process.start() 执行一个导入foo.py 的新python。这就是问题所在。新的foo 将创建另一个 子进程,该子进程将再次导入 foo.py。所以又一个进程被创建了。

除非python检测到问题并引发异常,否则会一直持续到您炸毁机器为止。

修复

Python 模块具有__name__ 属性。如果您将程序作为脚本运行,__name__ 是“ma​​in”,否则,__name__ 是模块的名称。因此,当一个多处理进程正在导入您的主脚本来设置您的环境时,它的名称不是__main__。您可以使用它来确保您的 MP 工作仅在父模块中完成。

import multiprocessing as mp

if __name__ == "__main__":
    # run as top level script, but not as imported module
    process = mp.Process(target=print, args=('foo',))
    process.start()
    process.join()

【讨论】:

感谢您的详细回答。但是,我使用的是 Mac OS (Mojave),但它仍然抛出错误。

以上是关于Python 多处理运行时错误的主要内容,如果未能解决你的问题,请参考以下文章

Python - 运行多个使用多处理的 python 脚本有时会影响性能和错误

处理包/模块中的错误时如何处理Python异常

使用TensorFlow-GPU + Python多处理时的错误?

运行时错误多处理互斥体 - 进程同步

从批处理文件运行多处理arcpy python

从 Python 多处理中的排队进程获取错误标志/消息