在 Python 多进程中,为什么子进程的名字是 __mp_main__?有没有办法用一个自定义的名字来覆盖它?

0 人关注
#!/usr/bin/env python3
import multiprocessing as mp
def child_process():
    print('Hi! My name is', __name__)
print('Hi! My name is', __name__)
if __name__ == '__main__':
    mp.Process(target=child_process).start()

上述代码的输出如下。

我感到困惑的是

  • Why the child process name is mp_main?
  • Why is it printed twice?
  • 3 个评论
    我假设这个名字是一个实现细节,主要问题是它不能被称为 __main__ 。至于为什么会打印两次,因为有两个进程。第一个是来自主进程,第二个是来自子进程加载脚本时,第三个打印是来自子进程执行 child_process() 时。
    我也是这么想的--第一个是在加载时,第二个是在执行时--但这没有意义。如果我想让子进程中的代码只执行一次,怎么办?另外,当我注释掉p1.start()时,只有主进程的名字被打印出来,也就是说。 主要
    "但这没有意义。如果我想让子进程中的代码只执行一次,怎么办?" 那么你必须把它放在 if __name__ == "__main__": ... 的后面。
    python
    multiprocessing
    python-multiprocessing
    Pawan
    Pawan
    发布于 2022-06-04
    2 个回答
    Blckknght
    Blckknght
    发布于 2022-06-04
    已采纳
    0 人赞同

    你在迷惑自己,因为你在两个不同的地方打印同一个信息。如果你给出明显的打印结果,你会更明白发生了什么。

    import multiprocessing as mp
    def child_process():
        print('Function print from:', __name__)
    print('Top level print from:', __name__)
    if __name__ == '__main__':
        mp.Process(target=child_process).start()
    

    With this code, you'll get:

    Top level print from: __main__
    Top level print from: __mp_main__
    Function print from: __mp_main__
    

    现在你可以看到,第一个打印输出是来自运行顶层代码的主模块。然后启动子进程,它也运行顶层代码。然后多处理逻辑在子进程内运行函数,你得到第三行。

    在子进程中再次加载模块可能会让人感到惊讶,但这是使用 spawn 模式 (这是默认的) 时 Python 多进程设计的一部分。顶层代码再次运行,但不是由if __name__ == "__main__"保护的部分,因为__name____mp_main__。不同的名称是故意的,以防止所有的代码(包括启动另一个子进程)不会在子进程中再次运行。让每个子进程也产生另一个进程会对你的系统造成不好的影响,因为你会创建无限数量的进程。

    还有一件事值得理解。__name__这个全局变量不是进程的名称,而是当前模块的名称。如果你对包含上述代码的模块进行import,它将打印出实际的模块名称,而不是__main____mp_main__,后者是分别用于作为脚本运行的模块和子进程中相同模块的特殊名称。丹-康斯坦丁斯库已经给出了一个很好的答案,解释了如何打印出实际的进程名称,如果你想这样的话。

    Dan Constantinescu
    Dan Constantinescu
    发布于 2022-06-04
    0 人赞同

    你可以通过使用 name 参数为子进程提供一个名称。也可以使用 current_process().name 来更好地识别哪个进程正在运行并显示其名称。

    import multiprocessing as mp
    def child_process():
        print('Hi! My name is', mp.current_process().name)
    print('Hi! My name is', mp.current_process().name)
    if __name__ == '__main__':
        mp.Process(target=child_process, name="child process").start()
    

    进程创建了自己的内存空间,正如注释中所指出的,打印的内容来自:主进程、加载脚本的子进程,然后是子进程执行child_process()函数。如果你用线程做同样的事情,你会看到只有两个打印,因为线程共享同一个内存空间。

    import threading
    def child_thread():
        print('Hi! My name is', threading.current_thread().name)