Python multiprocessing.Pool:AttributeError

Posted

技术标签:

【中文标题】Python multiprocessing.Pool:AttributeError【英文标题】:Python multiprocessing.Pool: AttributeError 【发布时间】:2019-02-15 07:42:00 【问题描述】:

我在一个类中有一个方法需要在一个循环中做很多工作,我想把工作分散到我所有的核心上。

我编写了以下代码,如果我使用普通的map(),它可以工作,但使用pool.map()会返回错误。

import multiprocessing
pool = multiprocessing.Pool(multiprocessing.cpu_count() - 1)

class OtherClass:
  def run(sentence, graph):
    return False

class SomeClass:
  def __init__(self):
    self.sentences = [["Some string"]]
    self.graphs = ["string"]

  def some_method(self):
      other = OtherClass()

      def single(params):
          sentences, graph = params
          return [other.run(sentence, graph) for sentence in sentences]

      return list(pool.map(single, zip(self.sentences, self.graphs)))


SomeClass().some_method()

错误一:

AttributeError: Can't pickle local object 'SomeClass.some_method..single'

为什么不能腌制single()?我什至尝试将 single() 移动到全局模块范围(不在类内部 - 使其独立于上下文):

import multiprocessing
pool = multiprocessing.Pool(multiprocessing.cpu_count() - 1)

class OtherClass:
  def run(sentence, graph):
    return False


def single(params):
    other = OtherClass()
    sentences, graph = params
    return [other.run(sentence, graph) for sentence in sentences]

class SomeClass:
  def __init__(self):
    self.sentences = [["Some string"]]
    self.graphs = ["string"]

  def some_method(self):
      return list(pool.map(single, zip(self.sentences, self.graphs)))


SomeClass().some_method()

我得到以下信息......

错误2:

AttributeError: Can't get attribute 'single' on module 'ma​​in' from '.../test.py'

【问题讨论】:

无论如何,对于您的原始代码:酸洗局部函数通常不起作用,尽管细节很复杂——而且,为了使调试更有趣,如果任何捕获的变量的值可以'不要被腌制,你会收到一条错误消息,它引用的是函数而不是那个值。 解决办法是把它变成一个方法或者一个全局函数,并把delex作为参数传入(你可以functools.partial)而不是捕获值。您的修改版本应该可以正常工作;问题是为什么它在data.SomeClass.reader 中查找,它看起来根本不像一个模块,而不是在模块中,大概是data。你能给我们一个minimal reproducible example 那个版本吗? @abarnert 我将这两个示例都更改为最小、完整和可验证,并更新了错误。它在data.SomeClass.reader 中查找的原因是因为这是文件的层次结构,因为我有多个数据源和每个数据源的阅读器。我删除了它,而是编写了一个具有相同错误的新类。 【参考方案1】:

错误 1:

AttributeError: Can't pickle local object 'SomeClass.some_method..single'

您通过将嵌套的目标函数 single() 移到顶层自己解决了这个错误。

背景:

Pool 需要腌制(序列化)它发送到其工作进程 (IPC) 的所有内容。 Pickling 实际上只保存函数的名称,而 unpickling 需要按名称重新导入函数。为此,需要在顶层定义函数,嵌套函数不能被子函数导入,并且已经尝试腌制它们会引发异常 (more)。


错误 2:

AttributeError: Can't get attribute 'single' on module 'main' from '.../test.py'

您在定义函数和类之前启动池,这样子进程就不能继承任何代码。将您的池启动移动到底部并使用 if __name__ == '__main__': 保护 (why?)

import multiprocessing

class OtherClass:
  def run(self, sentence, graph):
    return False


def single(params):
    other = OtherClass()
    sentences, graph = params
    return [other.run(sentence, graph) for sentence in sentences]

class SomeClass:
   def __init__(self):
       self.sentences = [["Some string"]]
       self.graphs = ["string"]

   def some_method(self):
      return list(pool.map(single, zip(self.sentences, self.graphs)))

if __name__ == '__main__':  # <- prevent RuntimeError for 'spawn'
    # and 'forkserver' start_methods
    with multiprocessing.Pool(multiprocessing.cpu_count() - 1) as pool:
        print(SomeClass().some_method())

附录

...我想把这项工作分散到我所有的核心。

关于 multiprocessing.Pool 如何进行分块工作的潜在有用背景:

Python multiprocessing: understanding logic behind chunksize

【讨论】:

完美。谢谢,我不知道 Pool 取决于位置【参考方案2】:

我无意中发现了一个非常讨厌的解决方案。它有效,只要你 使用def 语句。如果您声明要在 Pool.map 中使用的函数,并在解决它的函数的开头使用 global 关键字。但我不会在严肃的应用程序中依赖它?

import multiprocessing
pool = multiprocessing.Pool(multiprocessing.cpu_count() - 1)

class OtherClass:
  def run(sentence, graph):
    return False

class SomeClass:
  def __init__(self):
    self.sentences = [["Some string"]]
    self.graphs = ["string"]

  def some_method(self):
      global single  # This is ugly, but does the trick XD

      other = OtherClass()

      def single(params):
          sentences, graph = params
          return [other.run(sentence, graph) for sentence in sentences]

      return list(pool.map(single, zip(self.sentences, self.graphs)))


SomeClass().some_method()

【讨论】:

亲爱的上帝...安全吗?还是我会在 single 上跨类的不同实例获得一些竞争条件? 当然不是。甚至不要考虑在生产代码中使用它... xD

以上是关于Python multiprocessing.Pool:AttributeError的主要内容,如果未能解决你的问题,请参考以下文章

Python代写,Python作业代写,代写Python,代做Python

Python开发

Python,python,python

Python 介绍

Python学习之认识python

python初识