为啥 Python 的多处理模块在 Windows 上启动新进程时会导入 __main__?

Posted

技术标签:

【中文标题】为啥 Python 的多处理模块在 Windows 上启动新进程时会导入 __main__?【英文标题】:Why does Python's multiprocessing module import __main__ when starting a new process on Windows?为什么 Python 的多处理模块在 Windows 上启动新进程时会导入 __main__? 【发布时间】:2012-12-19 23:11:23 【问题描述】:

我正在为我的初学者学生使用一个库,并且我正在使用 Python 中的多处理模块。我遇到了这个问题:importing and using a module that uses multiprocessing without causing infinite loop on Windows

例如,假设我有一个模块mylibrary.py

# mylibrary.py

from multiprocessing import Process

class MyProcess(Process):
    def run(self):
        print "Hello from the new process"

def foo():
    p = MyProcess()
    p.start()

还有一个调用这个库的主程序:

# main.py

import mylibrary

mylibrary.foo()

如果我在 Windows 上运行 main.py,它会尝试将 main.py 导入新进程,这意味着代码会再次执行,从而导致进程生成的无限循环。我可以这样修复它:

import mylibrary

if __name__ == "__main__":
    mylibrary.foo()

但是,这对初学者来说相当混乱,而且似乎没有必要。新进程是在mylibrary中创建的,那为什么新进程不直接导入mylibrary呢?有没有办法解决这个问题而无需更改main.py

顺便说一下,我使用的是 Python 2.7。

【问题讨论】:

【参考方案1】:

Windows 没有fork,因此无法像现有进程一样创建新进程。所以子进程要再次运行你的代码,但是现在你需要一种方法来区分父进程和子进程,__main__就是它了。

这在此处的文档中有介绍:http://docs.python.org/2/library/multiprocessing.html#windows

我不知道另一种构造代码以避免分叉炸弹效应的方法。

【讨论】:

我确定我遗漏了一些东西,但我的问题是为什么子进程必须再次运行所有代码。为什么不只是启动新进程的模块? @Laura:它必须再次运行你的所有代码,因为如果没有,它就没有你的代码。子进程从头开始,如果你想让它有你的功能,它需要你的代码。 @NedBatchelder:这仍然不能真正回答问题。在发布的示例中,新进程只需要run 函数。为什么必须导入其他模块才能运行该功能? @Laura:关键是,应该在其中调用该模块的上下文,主脚本所在的上下文。由于 Windows 没有 fork,它可以不仅仅是将上下文复制到新进程中,它必须调用主脚本才能再次设置它。这就是您将实际程序代码放在if __name__ == "__main__": 块中的原因。导致它的一切都只是设置环境(所有导入、函数定义等)。 @Laura 回答 为什么子进程必须再次运行所有代码 - 当您这样做时,import mylibrary mylibrary 成为全局的一部分命名空间(sharedmain.py)因此,当您随后调用 mylibrary.foo() 时,foo 在此命名空间中运行,这会影响其行为。为了确保 foo 在子进程中的运行方式与在主进程中的运行方式完全相同,您必须在完全相同的命名空间(环境)中运行它,唯一的方法是从头开始运行所有内容,从执行 main.py. 开始

以上是关于为啥 Python 的多处理模块在 Windows 上启动新进程时会导入 __main__?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我没有看到通过 Python 中的多处理加速?

为啥带有酸洗的多处理序列化取决于范围?

具有大型数组的 Windows 上的 Python 多处理

python中的多处理模块和修改共享的全局变量

Python的多线程和多进程模块对比测试

python进程