2013-02-10 4 views
0

J'ai été choqué d'apprendre comment on peut trouver sur Internet des petits tutoriels et des guides sur les classes parallèles de python (PP) et de manipulation. J'ai rencontré un problème où je veux lancer quelques instances de la même classe et ensuite récupérer certaines variables (pour les instances lisant 5 fichiers de données en parallèle, puis récupérer leurs données). Voici un simple morceau de code pour illustrer mon problème:Travailler avec des classes et des pythons parallèles

import pp 

class TestClass: 
    def __init__(self, i): 
     self.i = i 

    def doSomething(self): 
     print "\nI'm being executed!, i = "+str(self.i) 
     self.j = 2*self.i 
     print "self.j is supposed to be "+str(self.j) 
     return self.i 

class parallelClass: 
    def __init__(self): 
     job_server = pp.Server() 
     job_list = [] 
     self.instances = [] # for storage of the class objects 
     for i in xrange(3): 
      TC = TestClass(i) # initiate a new instance of the TestClass 
      self.instances.append(TC) # store the instance 
      job_list.append(job_server.submit(TC.doSomething,(),())) # add some jobs to the job_list 
     results = [job() for job in job_list] # execute order 66... 

     print "\nIf all went well there's a nice bunch of objects in here:" 
     print self.instances 
     print "\nAccessing an object's i works ok, but accessing j does not" 
     print "i = "+str(self.instances[2].i) 
     print "j = "+str(self.instances[2].j) 

if __name__ == '__main__' : 
    parallelClass() # initiate the program 

J'ai ajouté des commentaires pour votre commodité. Qu'est-ce que je fais mal ici?

+0

Qu'est-ce qui ne va pas? Quel est le résultat attendu de votre programme et qu'obtenez-vous à la place? A propos: pourquoi utilisez-vous une classe '__init__' quand vous voulez quelque chose comme une fonction' main'. Je ne m'attendrais jamais à ce que la création d'une instance d'une classe bloque tout mon programme. – Bakuriu

+0

@Bakuriu Je m'attendrais à ce que le programme affiche la valeur de 'j' d'une instance. J'obtiens une instance 'AttributeError: TestClass n'a pas d'attribut 'j'' à la place. Ne vous inquiétez pas de '__init__', ce code est juste une représentation simplifiée de mon programme actuel. – MPA

+0

Je crois que le problème est que le code est exécuté sur différents objets. Python parallèle simple décante les objets et les envoie aux sous-processus, de sorte que vous modifiez l'état local des objets, ce qui n'affecte pas les instances d'origine. Vous pouvez vérifier cette impression de 'id' de' self' dans 'doSomething' et' id' des éléments dans 'instances'. – Bakuriu

Répondre

1

Vous devez utiliser callbacks

A callbacks est une fonction que vous passez à l'appel submit. Cette fonction sera appelée avec le résultat du travail en tant qu'argument (have a look at the API for more arcane usage).

Dans votre cas

Mettre en place un rappel:

class TestClass: 
    def doSomething(self): 
     j = 2 * self.i 
     return j # It's REQUIRED that you return j here. 

    def set_j(self, j): 
     self.j = j 

Ajouter le rappel au travail soumettre appel

class parallellClass: 
     def __init__(self): 
      #your code... 
      job_list.append(job_server.submit(TC.doSomething, callback=TC.set_j)) 

Et vous avez terminé.

J'ai apporté quelques améliorations au code pour éviter d'utiliser self.j dans l'appel doSomething et utiliser uniquement une variable locale j.

Comme mentionné dans les commentaires, dans pp, vous communiquez uniquement le résultat de votre travail. C'est pourquoi ont pour renvoyer cette variable, elle sera transmise au rappel.