在Python多重处理中使用__name __ =='__ main__'的解决方法

问题描述:

众所周知,我们需要在使用if __name__ == '__main__'的Python中运行代码multiprocessing时保护main()在Python多重处理中使用__name __ =='__ main__'的解决方法

我明白,这是在某些情况下,必要时给予进入主定义的函数,但我不明白这是为什么在这种情况下,有必要:

​​

import numpy as np 
from multiprocessing import Pool 
class Something(object): 
    def get_image(self): 
     return np.random.rand(64,64) 

    def mp(self): 
     image = self.get_image() 
     p = Pool(2) 
     res1 = p.apply_async(np.sum, (image,)) 
     res2 = p.apply_async(np.mean, (image,)) 
     print(res1.get()) 
     print(res2.get()) 
     p.close() 
     p.join() 

main.py

from file2 import Something 
s = Something() 
s.mp() 

Something工作所需的所有功能或进口是​​58的一部分。为什么子过程需要重新运行main.py

我认为__name__解决方案不是很好,因为这阻止了我分发​​的代码,因为我无法确定它们是保护它们的主体。 对于Windows没有解决方法吗? 是如何解决的软件包 -

编辑(因为我从来没有遇到过不保护我的主要有任何包中的任何问题,他们只是没有使用多?): 我知道,这是因为没有实现fork()的视窗。我只是问,如果有一个黑客让翻译在​​开始,而不是main.py,我可以肯定的是​​是自给自足

+3

'if __name__ =='__main __''hack只在Windows上需要,因为该平台没有'fork()'。如果您选择_any_其他操作系统,则不需要它。 –

+0

OP,只是为了确认,你在windows上是否正确? –

+1

如果我正确理解你,你正在编写'file2.py'作为一个库,并且你想要支持像'main.py'这样的用户代码(将来可能会被其他人编写)。不幸的是,我不认为有什么办法可以保护你的用户免受'multiprocessing'的需求。您可能只需要记录您的模块需要将脚本代码放在'if __name__ ==“__main __”'块中,以便在模块导入时不会运行任何内容。 – Blckknght

主要模块导入(但__name__ != '__main__'因为Windows正试图以模拟分叉类似的行为一个没有分叉的系统multiprocessing没有办法知道你没有在你的主模块中做任何重要的事情,所以导入完成“以防万一”来创建一个类似于主进程中的环境如果没有这样做,那么在子进程中可能无法正确执行主副本中发生的各种事件(例如导入,具有持久副作用的配置调用等)。

因此,如果他们不保护他们的__main__,代码不是多处理安全的(也不是单元测试安全,导入安全等)。 if __name__ == '__main__':保护包装应该是所有正确的主要模块的一部分。继续并分发,并提供关于要求多处理安全主模块保护的说明。

当使用“重生”启动方法,新工艺是Python解释是从零开始。对于子流程中的新Python解释器来说,不可能找出需要导入的模块,因此它们再次导入主模块,然后再导入其他所有模块。这意味着它必须可以导入主模块而没有任何副作用。

如果您使用的是与Windows不同的平台,则可以使用“fork”开始方法,而不会出现此问题。

这就是说,使用if __name__ == "__main__":有什么问题?它还有很多额外的好处,例如文档工具将能够处理您的主要模块,单元测试更容易等,所以您应该在任何情况下使用它。

if __name__ == '__main__'在windows上是需要的,因为windows没有进程的“fork”选项。例如,你可以在fork这个进程中,所以父进程将被复制,副本将成为子进程(并且它将有权访问你已经在父进程中加载​​的已经导入的代码)

既然你不能在Windows中分叉,python只是导入父进程导入的所有代码在子进程中。这会产生类似的效果,但是如果你不执行这个技巧,这个导入将在子进程中再次执行你的代码(这将使它创建它自己的子进程,等等)。

因此,即使在您的示例中,main.py也会再次导入(因为所有文件都会再次导入)。 python cant猜测子进程应该导入什么特定的python脚本。

FYI还有其他的限制,你应该知道像使用全局变量,你可以看到在这里https://docs.python.org/2/library/multiprocessing.html#windows