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.py
或python -m foo
直接执行时才等于"__main__"
。这确保如果将脚本作为模块导入,则不会调用Process()
。
【讨论】:
所以不能在一个模块中使用多处理? @jul 可以,但对Process()
的实际构造函数调用必须包装为“单例命令”。这是因为 Windows 不仅会克隆进程,而且必须重新执行 python 解释器的副本,这意味着“主模块”将被导入两次。本质上,将您的导入“活动”保持在最低限度。导入完成后,你可以对模块中的类和函数做任何你想做的事情。
@user2097818 您能否更详细地解释一下“单例命令”的含义?本质上,我想知道是否可以生成一个函数(在我将导入的某个模块中定义)并执行该函数而不将其包装在“if name == 'main'”中内部使用多处理?
学究起来,__name__ == '__main__'
不总是适用于 __main__.py
吗?以上是关于Windows 上的 python 多处理,如果 __name__ == "__main__"的主要内容,如果未能解决你的问题,请参考以下文章
尝试python多处理的Windows上的RuntimeError
MacOS 和 Windows 上的 Python 多处理行为
Windows 上的 Python DEAP 和多处理:AttributeError
Windows 上的 Python 2.7,“assert main_name not in sys.modules, main_name”适用于所有多处理示例