在 Jupyter Notebook 中给出 AttributeError 的多处理示例

问题描述 投票:0回答:5

我正在尝试在我的代码中实现多处理,因此,我认为我应该从一些示例开始学习。 我使用了此文档中找到的第一个示例。

from multiprocessing import Pool
def f(x):
    return x*x

if __name__ == '__main__':
    with Pool(5) as p:
        print(p.map(f, [1, 2, 3]))

当我运行上面的代码时,我得到一个

AttributeError: can't get attribute 'f' on <module '__main__' (built-in)>
。 我不知道为什么会收到此错误。 如果有帮助的话,我也在使用 Python 3.5。

python multithreading jupyter-notebook multiprocessing python-multiprocessing
5个回答
172
投票

这个问题似乎是multiprocessing.Pool的设计特性。请参阅https://bugs.python.org/issue25053。由于某种原因,池并不总是适用于导入模块中未定义的对象。因此,您必须将函数写入不同的文件并导入模块。

文件:defs.py

def f(x):
    return x*x

文件:run.py

from multiprocessing import Pool
import defs

 if __name__ == '__main__':
    with Pool(5) as p:
        print(p.map(defs.f, [1, 2, 3]))

如果您使用 print 或其他内置函数,该示例应该可以工作。如果这不是一个错误(根据链接),则给出的示例选择不当。


153
投票

multiprocessing
模块在 IPython 使用方面有一个主要限制:

此包中的功能需要

__main__
模块 孩子们可以导入的。 [...]这意味着一些例子,例如 因为
multiprocessing.pool.Pool
示例在 交互式口译员。 [来自文档]

幸运的是,

multiprocessing
模块有一个名为
multiprocess
的分支,它使用 dill 而不是 pickle 进行序列化并方便地解决了这个问题。

只需安装

multiprocess
并在导入中将
multiprocessing
替换为
multiprocess

import multiprocess as mp

def f(x):
    return x*x

with mp.Pool(5) as pool:
    print(pool.map(f, [1, 2, 3, 4, 5]))

当然,按照这个答案中的建议将代码外部化也可以,但我发现它非常不方便:这不是我使用 IPython 环境的原因(以及如何)。

multiprocessing
不能立即在 IPython 环境中工作,请使用其分支
multiprocess
代替。


13
投票

此答案适用于 2021 年中在 Windows 10 上遇到此错误的用户。

自从我自己发现这个错误以来,我已经对此错误进行了一些研究。在运行有关多处理的官方 Python 3 文档中的任何示例时,我都会收到此错误。

测试环境:

    x86 Windows 10.0.19043.1165 + Python 3.9.2 - 有错误
  • x86 Windows 10.0.19043.1165 + Python 3.9.6 - 有错误
  • x86 Windows 10.0.19043.1110 + Python 3.9.6 - 有错误
  • ARM Windows 10.0.21354.1 + Python 3.9.6 - 无错误(来自 DEV 分支的版本)
  • ARM macOS 11.5.2 + Python 3.9.6 - 无错误
我没有办法在其他条件下测试这种情况。但我的猜测是问题出在 Windows 上,因为开发版本“10.0.21354.1”中没有这样的错误,但这个 ARM 版本可能有 x86 模拟。

另请注意,Python 3.9.2 发布时(2 月)并没有这样的 bug。由于我一直在同一台计算机上工作,所以我对以前工作的代码停止工作,只有 Windows 版本发生变化的情况感到惊讶。

我无法在Python错误跟踪器中找到具有类似情况的错误请求(我可能做了一个糟糕的搜索)。而标有“正确答案”的消息则指的是不同的情况。该问题很容易重现,您可以尝试在新安装的 Windows 10 + Python 3 上遵循多处理文档中的任何示例。

稍后我将有机会查看Python 3.10和最新版本的Windows 10。 我对 Windows 11 背景下的这种情况也很感兴趣。

如果您有有关此错误的信息(链接到错误跟踪器或类似内容),请务必分享。

此刻我切换到Linux继续工作。


6
投票
为什么不使用

joblib

?您的代码相当于:

# pip install joblib from joblib import Parallel, delayed def f(x): return x*x res = Parallel( n_jobs=5 )( delayed(f)(x) for x in [1, 2, 3] )
    

-2
投票
如果您使用 Jupyter 笔记本(如 OP),则在单独的单元中定义函数并首先执行该单元可以解决问题。接受的答案也有效,但需要更多工作。之前定义函数(即在池上方)是不够的。它必须位于首先执行的完全不同的笔记本单元中。

© www.soinside.com 2019 - 2024. All rights reserved.