2009-09-04 7 views
4

Je travaille sur un serveur xmlrpc qui doit effectuer certaines tâches cycliquement. Je me sers tordu comme le noyau du service de xmlrpc mais je suis en cours d'exécution dans un petit problème:Multiprocesseur Python avec le réacteur twisted

class cemeteryRPC(xmlrpc.XMLRPC): 

    def __init__(self, dic): 
     xmlrpc.XMLRPC.__init__(self) 


    def xmlrpc_foo(self): 
     return 1 


    def cycle(self): 
     print "Hello" 
     time.sleep(3) 


class cemeteryM(base): 

    def __init__(self, dic): # dic is for cemetery 
     multiprocessing.Process.__init__(self) 
     self.cemRPC = cemeteryRPC() 


    def run(self): 
     # Start reactor on a second process 
     reactor.listenTCP(c.PORT_XMLRPC, server.Site(self.cemRPC)) 
     p = multiprocessing.Process(target=reactor.run) 
     p.start() 

     while not self.exit.is_set(): 
      self.cemRPC.cycle() 
      #p.join() 


if __name__ == "__main__": 

    import errno 
    test = cemeteryM() 
    test.start() 

    # trying new method 
    notintr = False 
    while not notintr: 
     try: 
      test.join() 
      notintr = True 
     except OSError, ose: 
      if ose.errno != errno.EINTR: 
       raise ose 
     except KeyboardInterrupt: 
      notintr = True 

Comment dois-je aller à se joindre à ces processus en deux afin que leurs joints respectifs ne bloque pas?

(je suis assez confus par « rejoindre ». Pourquoi serait-il bloquer et je l'ai googlé, mais ne peut pas trouver beaucoup explication utile à l'utilisation de rejoindre. Quelqu'un peut-il me l'expliquer?)

Cordialement

Répondre

11

Avez-vous vraiment besoin d'exécuter Twisted dans un processus séparé? Cela me semble assez inhabituel. Essayez de penser à Twisted's Reactor comme votre boucle principale - et de suspendre tout ce dont vous avez besoin - plutôt que d'essayer d'exécuter Twisted en arrière-plan. La manière la plus normale d'effectuer ce type d'opération serait d'utiliser .callLater de Twisted ou d'ajouter un objet LoopingCall au Reactor.

par exemple.

from twisted.web import xmlrpc, server 
from twisted.internet import task 
from twisted.internet import reactor 

class Example(xmlrpc.XMLRPC):   
    def xmlrpc_add(self, a, b): 
     return a + b 

    def timer_event(self): 
     print "one second" 

r = Example() 
m = task.LoopingCall(r.timer_event) 
m.start(1.0) 

reactor.listenTCP(7080, server.Site(r)) 
reactor.run() 
+1

oh homme merci beaucoup c'est pourquoi j'ai besoin exactement. Où avez-vous entendu parler de LoopingCall? C'est pourquoi je déteste tordu - les documentations ne suffisent pas d'une part, tandis que les API sont si grands que vous avez tendance à négliger les bits importants. –

+0

Je sais ce que vous voulez dire - Twisted peut être difficile à apprendre, mais une fois que vous avez l'idée, cela fonctionne très bien! Le livre d'O'Reilly est assez ancien maintenant, mais il explique très bien les choses, donc je recommande d'en obtenir une copie si vous voulez en faire beaucoup plus avec Twisted. –

+1

Je vous recommande la souscription à leur liste de diffusion. Si vous lisez assez de réponses de la part du gourou, une partie de celle-ci commence à coller * l'osmose cérébrale *. – DrBloodmoney

3

Hey asdvawev - .join() à multitraitement fonctionne comme .join() dans le filetage - il est un blocage d'appel le thread principal va attendre que le travailleur de fermer. Si le travailleur ne s'arrête jamais, alors .join() ne reviendra jamais. Par exemple:

class myproc(Process): 
    def run(self): 
     while True: 
      time.sleep(1) 

appel course sur cela signifie que join() ne sera jamais, jamais revenir. En règle générale pour éviter cela, je vais utiliser un objet événement() passé dans le processus de l'enfant pour me permettre de signaler l'enfant quand sortir:

class myproc(Process): 
    def __init__(self, event): 
     self.event = event 
     Process.__init__(self) 
    def run(self): 
     while not self.event.is_set(): 
      time.sleep(1) 

Par ailleurs, si votre travail est encapsulé dans une file d'attente - vous pouvez simplement faites en sorte que le processus fils fonctionne hors de la file d'attente jusqu'à ce qu'il rencontre une sentinelle (généralement une entrée None dans la file d'attente), puis fermez-le. Ces deux suggestions signifient qu'avant d'appeler .join() vous pouvez envoyer l'événement, ou insérer la sentinelle et lorsque join() est appelée, le processus terminera sa tâche en cours et quittera correctement.

Questions connexes