Карта многопроцессорного пула Python: AttributeError: Невозможно выбрать локальный объект - PullRequest
0 голосов
/ 10 сентября 2018

У меня есть метод внутри класса, который должен выполнять большую работу в цикле, и я хотел бы распределить работу по всем моим ядрам.

Я написал следующий код, который работает, если я использую обычный 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: Невозможно выбрать локальный объект '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()

и я получаю следующую ошибку:

AttributeError: Невозможно получить атрибут 'single' для модуля ' main ' из '... / test.py'

1 Ответ

0 голосов
/ 11 сентября 2018

Вы запускаете пул до того, как определили свою функцию и классы, таким образом, дочерние процессы не могут наследовать какой-либо код.Переместите ваш бассейн вверх и защитите его с помощью 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())
...