Python多处理池映射:AttributeError:无法腌制本地对象

Ami*_*mit 13 python multiprocessing python-multiprocessing

我在类中有一个方法,该方法需要循环执行大量工作,我想将工作分散到我的所有核心上。

我编写了以下代码,如果我使用normal 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()
Run Code Online (Sandbox Code Playgroud)

错误:

AttributeError:无法腌制本地对象“ 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()
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

AttributeError:无法从'... / test.py' 获取模块' main ' 上的属性'single '

Mar*_*zki 18

我无意中发现了一个非常讨厌的解决方案。只要您使用def语句,它就可以工作。如果声明的功能,要在使用Pool.mapglobal能够解决它的关键字在函数的开始。但我不会在严肃的应用中依赖这个

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()
Run Code Online (Sandbox Code Playgroud)

  • 当然不是。甚至不要考虑在生产代码中使用它......xD (4认同)
  • 亲爱的上帝……安全吗?或者我会在类的不同实例中得到“single”的一些竞争条件吗? (3认同)

Dar*_*aut 12

错误1:

AttributeError:无法腌制本地对象“ SomeClass.some_method..single”

您可以通过将嵌套的目标函数single()移到顶层来自己解决此错误。

背景:

Pool需要对其发送到其工作进程(IPC)的所有内容进行腌制(序列化)。酸洗实际上仅保存函数的名称,而酸洗则需要按名称重新导入该函数。为此,必须在顶层定义函数,子级将无法导入嵌套函数,并且已经尝试对其进行腌制会引发异常(更多)。


错误2:

AttributeError:无法从“ ... / test.py”获取模块“ main”上的属性“ single”

定义函数和类之前先启动池,这样子进程就不能继承任何代码。将您的池启动到最底部并用以下方法保护(为什么?if __name__ == '__main__':

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())
Run Code Online (Sandbox Code Playgroud)

附录

...我希望将工作分散到我的所有核心。

有关multiprocessing.Pool分块工作方式的潜在帮助背景:

Python多处理:了解块大小背后的逻辑

  • 完美的。谢谢,我不知道 Pool 取决于位置 (6认同)