Windows 上的 python 多处理,如果 __name__ == "__main__"

Posted

技术标签:

【中文标题】Windows 上的 python 多处理,如果 __name__ == "__main__"【英文标题】:python multiprocessing on windows, if __name__ == "__main__" 【发布时间】:2013-12-11 22:02:11 【问题描述】:

在 Windows 7(64 位)上运行 python 2.7。

在阅读库模块 multiprocessing 的文档时,它多次声明了 __main__ 模块的重要性,包括条件(尤其是在 Windows 中):

if __name__ == "__main__":
    # create Process() here

我的理解是,你不想在模块的全局命名空间中创建 Process() 实例(因为当子进程导入模块时,他会不经意地产生另一个)。

不过,我不必将流程管理器放在我的包执行层次结构的最顶层(在 PARENT 中执行)。只要我的 Process() 是在类方法中创建、管理和终止的,甚至是在函数闭包中。只是不在***模块命名空间中。

我是否正确理解了这个警告/要求?


编辑

在前两个回复之后,我添加了这句话。这是 2.7 文档中第 16.6 节多处理的介绍。

注意:此包中的功能要求子组件可以导入 __main__ 模块。这在编程中有所介绍 指南但是值得在这里指出。这意味着一些 示例,例如 multiprocessing.Pool 示例在 交互式解释器...

【问题讨论】:

迂腐提示:当代码实际运行时,if __name__ == '__main__': 中的变量仍在模块的 命名空间 中。但是,在导入模块时不会执行代码。 (即,我相信如果您导入程序的主模块,您可以从其主块中检索变量作为模块属性。) 所以在if 中创建的@millimoose 变量可供Windows 机器上的所有衍生进程访问,对吗?即使它们没有在if之外声明? @Kartik - 我不确定我是否理解这个问题,反正已经三年了。我认为它们将是可访问的,但它们的值将是虚假的。我建议您编写一些测试代码来找出您的想法,如果您有任何具体问题,请在 SO 上发布一个新问题。 【参考方案1】:

您不必从模块的“顶层”调用Process()。 从类方法调用Process 完全没问题。

唯一需要注意的是,当模块被导入时,您不能允许调用Process()

由于 Windows 没有 fork,因此多处理模块会启动一个新的 Python 进程并导入调用模块。如果在导入时调用Process(),那么这会引发无限连续的新进程(或直到您的机器耗尽资源)。这就是在里面隐藏对Process()的调用的原因

if __name__ == "__main__"

因为这个if-statement 中的语句不会在导入时被调用。

【讨论】:

我相信我明白你的意思了。我对原始问题进行了编辑,以更好地说明我的困惑。 问:“为什么需要能够导入__main__?”。答:在 Windows 上,调用 Process() 会导致调用模块被导入。使用multiprocessing 时,您需要在编写代码时期望调用模块会被导入。 我认为我分析过度了。我将计划导入我的多处理模块。事实上,它永远不会被执行,因为我的程序也将导入它,并且必须在创建任何 Process() 实例之前与 Factory 类进行交互。 这是否意味着joblib's documentation 中的警告,说不应在if __name__ == '__main__' 块之外执行任何代码,是不是矫枉过正? @ziyuang:重要的是您了解if-block 之外的代码会发生什么——特别是在Windows 上,每个生成的进程都会重新导入调用模块,从而重新执行if-block 之外的所有代码。 joblib 文档说,“只有导入和定义”。定义可以包括变量和函数的定义。请确保不要在 if-block 之外生成子进程,因为(在 Windows 上)这肯定会导致 fork bomb。【参考方案2】:

__name__ 仅在脚本已通过python foo.pypython -m foo 直接执行时才等于"__main__"。这确保如果将脚本作为模块导入,则不会调用Process()

【讨论】:

所以不能在一个模块中使用多处理? @jul 可以,但对Process() 的实际构造函数调用必须包装为“单例命令”。这是因为 Windows 不仅会克隆进程,而且必须重新执行 python 解释器的副本,这意味着“主模块”将被导入两次。本质上,将您的导入“活动”保持在最低限度。导入完成后,你可以对模块中的类和函数做任何你想做的事情。 @user2097818 您能否更详细地解释一下“单例命令”的含义?本质上,我想知道是否可以生成一个函数(在我将导入的某个模块中定义)并执行该函数而不将其包装在“if name == 'main'”中内部使用多处理? 学究起来,__name__ == '__main__' 不总是适用于 __main__.py 吗?

以上是关于Windows 上的 python 多处理,如果 __name__ == "__main__"的主要内容,如果未能解决你的问题,请参考以下文章

尝试python多处理的Windows上的RuntimeError

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

MacOS 和 Windows 上的 Python 多处理行为

Windows 上的 Python DEAP 和多处理:AttributeError

Windows 上的 Python 2.7,“assert main_name not in sys.modules, main_name”适用于所有多处理示例

从 MAC 上的批处理文件运行 Python 脚本 [关闭]