当前位置:  开发笔记 > 编程语言 > 正文

Python多处理池卡住了

如何解决《Python多处理池卡住了》经验,为你挑选了1个好方法。

我正在尝试运行在web中找到的python的multiprocessing.pool模块的一些示例代码.代码是:

def square(x):
    return x * x
if __name__ == '__main__':
    pool = Pool(processes=4)
    inputs = [0, 1, 2, 3, 4]
    outputs = pool.map(square, inputs)

但是当我尝试运行它时,它永远不会完成执行,我必须重新启动我的IpythonNotebook笔记本的内核.有什么问题?



1> KT...:

正如您可能从评论中指出的答案中读到的那样multiprocessing.Pool,一般来说,不应期望在交互式解释器中工作得很好.要理解为什么会这样,考虑Pool它的工作原理:

它分叉python worker,向他们传递当前Python文件的名称.

然后工人基本上做import ,并听取主人的消息.

主机通过酸洗将函数名称和函数参数一起发送给工人.请注意,函数本身无法发送,因为pickle协议不允许这样做.

当您尝试从交互式提示中执行此过程时,没有合理的"当前Python文件"传递给子项以进行导入.此外,您在交互式提示中定义的函数不是任何模块的一部分(它们是动态定义的),因此子项不能从该不存在的模块中导入.因此,最简单的方法就是避免multiprocessing在IPython中使用.无论如何,IPython并行更好:)


为了完整起见,我还检查了在Windows 8上运行在Python 2.7下的IPython 4的特定情况下究竟发生了什么(我可以观察到解释器也被卡住了).有趣的是,IPython首先陷入困境的原因并不是上面提到的那个.

事实证明,多处理检查是否__main__.__file__已定义,如果没有,则sys.argv[0]作为"当前文件名"发送给子节点.在(我的版本)IPython sys.argv[0]等于的情况下C:\Dev\Anaconda\lib\site-packages\ipykernel\__main__.py.

不幸的是,工作流程在启动之前就会检查他们要导入的文件是否已经存在sys.modules.第488行multiprocessing/forking.py说:

assert main_name not in sys.modules, main_name

如果main_name__main__(就像ipython的工作人员的情况那样),这个断言失败,工人无法启动.但是,相同的代码足够"智能"来检查传递的名称是否是ipython,在这种情况下它不会执行此类检查,也不会导入任何内容.

因此,工人未能启动的问题可以通过定义__main__.__file__为等于的丑陋黑客来解决ipython.以下代码可以从IPython单元格中正常工作:

import sys
sys.modules['__main__'].__file__ = 'ipython'
from multiprocessing import Pool

pool = Pool(processes=4)
inputs = [0, 1, 2, 3, 4]
outputs = pool.map(abs, inputs)

请注意,此示例要求工作人员计算abs内置函数.如果您要求工作人员计算您在笔记本中定义的函数,它将失败(优雅地,例外).

事实证明,原则上你可以进一步处理黑客行为,并使用他们的代码手动腌制将你的功能发送给工人.你可以找到这样一个黑客的一个很酷的例子在这里.

推荐阅读
凹凸曼00威威_694
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有