繁体   English   中英

Python multiprocessing.Pool:AttributeError

[英]Python multiprocessing.Pool: AttributeError

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

我编写了以下代码,如果我使用普通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()

错误 1:

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()

我得到以下...

错误 2:

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

错误 1:

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

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

背景:

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


错误 2:

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

定义函数和类之前启动池,这样子进程就不能继承任何代码。 将您的池启动到底部并使用if __name__ == '__main__':保护(为什么? )它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())

附录

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

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

Python 多处理:理解 chunksize 背后的逻辑

我无意中发现了一个非常讨厌的解决方案。 只要您使用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()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM