>我有一个简单的函数,我打算使用 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()
大多数在线帖子都建议与这个答案相同。
我添加了它并且它可以工作,但我似乎不明白为什么这么简单的代码段需要它。
没有 __name__=="__main__" 的代码(抛出运行时错误)
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__" 的代码(不会引发运行时错误)
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()
执行一个新的python,它导入foo.py
。这就是问题所在。该新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()