首页 > 解决方案 > 在当前进程在 python 中完成其引导阶段之前,已尝试启动一个新进程

问题描述

我尝试在 python 上运行此代码

import multiprocessing

manager = multiprocessing.Manager()
final_list = manager.list()

input_list_one = ['one', 'two', 'three', 'four', 'five']
input_list_two = ['six', 'seven', 'eight', 'nine', 'ten']

def worker(data):
    for item in data:
        final_list.append(item)

if __name__ == '__main__':    

    process1 = multiprocessing.Process(target=worker, args=[input_list_one])
    process2 = multiprocessing.Process(target=worker, args=[input_list_two])

    process1.start()
    process2.start()
    process1.join()
    process2.join()

    print(final_list)

但是发生了这个错误:RuntimeError:

An attempt has been made to start a new process before the
current process has finished its bootstrapping phase.

This probably means that you are not using fork to start your
child processes and you have forgotten to use the proper idiom
in the main module:

    if __name__ == '__main__':
        freeze_support()
        ...

The "freeze_support()" line can be omitted if the program
is not going to be frozen to produce an executable.

标签: pythonmultiprocessing

解决方案


问题在于声明:

manager = multiprocessing.Manager()

它通过启动服务器进程来发挥其“魔力”。因此,该语句需要与托管列表的创建一起移动到if __name__ = '__main__':块内,现在需要将其作为附加参数传递给您的流程函数,worker. 实际上,您不妨将所有实际上不需要在if __name__ = '__main__':块内以提高效率的声明移动到全局范围内,否则它们将被创建的每个新进程不必要地执行。

import multiprocessing

def worker(final_list, data):
    for item in data:
        final_list.append(item)

if __name__ == '__main__':
    manager = multiprocessing.Manager()
    final_list = manager.list()

    input_list_one = ['one', 'two', 'three', 'four', 'five']
    input_list_two = ['six', 'seven', 'eight', 'nine', 'ten']

    process1 = multiprocessing.Process(target=worker, args=[final_list, input_list_one])
    process2 = multiprocessing.Process(target=worker, args=[final_list, input_list_two])

    process1.start()
    process2.start()
    process1.join()
    process2.join()

    print(final_list)

印刷:

['six', 'seven', 'eight', 'nine', 'one', 'ten', 'two', 'three', 'four', 'five']

让我详细说明一下我的答案:

您显然在使用该spawn方法创建新进程的平台上运行。这意味着要启动一个新进程,会创建一个新的空地址空间,并针对源运行 Python 解释器的新实例。在调用实例的目标之前Process,将首先执行源文件中在全局范围内的任何语句以初始化进程,内的任何语句除外if __name__ = '__main__':(因为__name__新进程的值不会是 '__main__') . 这就是为什么您需要将创建新进程的代码放在这样的块中,即避免陷入无限循环创建新进程的递归循环如果这没有被发现。在您的情况下,它并没有未被检测到,并且您收到了您看到的错误消息。

但是,即使创建Manager实例并没有导致创建新进程,您的程序也不会是正确的。将语句置于final_list = manager.list()全局范围意味着您正在运行的程序中的所有三个进程都将访问final_list.


推荐阅读