与多处理错误的另一个混淆是,“模块”对象没有属性“ f”


68

我知道这已经得到了回答,但是直接执行脚本“ python filename.py”似乎不起作用。我在SuSE Linux上有Python 2.6.2。

码:

#!/usr/bin/python
# -*- coding: utf-8 -*-
from multiprocessing import Pool
p = Pool(1)
def f(x):
    return x*x
p.map(f, [1, 2, 3])

命令行:

> python example.py
Process PoolWorker-1:
Traceback (most recent call last):
File "/usr/lib/python2.6/multiprocessing/process.py", line 231, in _bootstrap
    self.run()
File "/usr/lib/python2.6/multiprocessing/process.py", line 88, in run
    self._target(*self._args, **self._kwargs)
File "/usr/lib/python2.6/multiprocessing/pool.py", line 57, in worker
    task = get()
File "/usr/lib/python2.6/multiprocessing/queues.py", line 339, in get
    return recv()
AttributeError: 'module' object has no attribute 'f'


@jb。该帖子比此帖子晚很多,这是2010年,那是2013年
gatoatigrado 2014年

2
年龄是不确定的,关于元数据的共识是应该选择具有更好答案的问题,而另一个具有IMO更好答案的问题。
jb。

Answers:


131

重组代码,以便f()在创建Pool实例之前定义函数。否则,工作人员将看不到您的功能。

#!/usr/bin/python
# -*- coding: utf-8 -*-

from multiprocessing import Pool

def f(x):
    return x*x

p = Pool(1)
p.map(f, [1, 2, 3])

1
注意:几年后,我开始编写imap替代项[ github.com/gatoatigrado/vimap ],这使此错误更加困难(并在分叉线程时很清楚)。
gatoatigrado 2013年

1
@Bartosz,您知道为什么在ipython笔记本中这不是问题吗?
Framester 2014年

@Framester:奇怪的是,ipython笔记本正在使用类似“ spawn”的方法进行多处理,而不是基于“ fork”的方法。基于生成的方法是启动一个新进程并导入主模块(但不作为__main__,以防止其执行if __name__ == '__main__:`东西),或者将pickle解释器状态传输给子进程。fork语义更快,但只能在单台计算机上运行,​​而不能在Windows上运行。可以使生成语义在任何地方都可以使用(例如Windows w / o fork),并且可以在群集上使用,并且ipython笔记本适用于多机情况。
ShadowRanger

5

这个作品:

#!/usr/bin/python
# -*- coding: utf-8 -*-
from multiprocessing import Pool

def f(x):
    return x*x

if __name__ == "__main__":
    p = Pool(1)
    p.map(f, [1, 2, 3])

我不确定100%为什么您的代码不起作用,但是我想原因是由multiprocessing模块启动的子进程尝试导入主模块(以访问您定义的方法),而该if __name__ == "__main__"节不是必需的在设置池的位置执行初始化代码。


如果必须通过Windows上的解释器运行这样的代码,是否可以解决?这就是我在Gimp Python Console插件中进行一些Python-Fu编程时遇到的情况。
jxramos

@Tamás,它对我也不起作用from multiprocessing import PoolImportError: cannot import name Pool
Houy Narun

1

一种可能是您的python文件与模块具有相同的名称:

  • test.py
  • 测试/
    • __init__.py

在pickle.py中,您的错误来自:

    def find_class(self, module, name):
      # Subclasses may override this
      __import__(module)
      mod = sys.modules[module] # <- here mod will reference your test/__init__.py
      klass = getattr(mod, name)
      return klass


1

这是因为在p = Pool(1)创建函数f之前,主进程会先分叉进程(线程与进程)。如Bartosz所述,产生的进程无法访问新功能。

def f1(x):
    ...

p = Pool(1) # p is spawned and is now an independent process, knows f1

def f(x): # p doesn't not share this object
    ...
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.