web-dev-qa-db-fra.com

Python Carte du pool de multitraitement: AttributeError: impossible de décaper un objet local

J'ai une méthode à l'intérieur d'une classe qui a besoin de faire beaucoup de travail en boucle, et je voudrais répartir le travail sur tous mes cœurs.

J'ai écrit le code suivant, qui fonctionne si j'utilise un map normal, mais avec pool.map renvoie une erreur.

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

Erreur:

AttributeError: impossible de décaper l'objet local 'SomeClass.some_method..single'

Pourquoi ne peut-il pas décaper single? J'ai même essayé de déplacer single vers la portée du module global (pas à l'intérieur de la classe - le rend indépendant du contexte):

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

et j'obtiens l'erreur suivante:

AttributeError: Impossible d'obtenir l'attribut 'single' sur le module 'main' de '.../test.py'

9
Amit

Vous démarrez le pool avant de définir votre fonction et vos classes, de cette façon les processus enfants ne peuvent hériter aucun code. Déplacez votre piscine au fond et protégez-la avec 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())
7
Darkonaut