Python 多处理运行时错误

Python multiprocessing RuntimeError

我有一个简单的函数,我打算使用 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()

大多数在线帖子都这样建议 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()

在 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__就是“main”,否则,__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()