2009-09-04 5 views
4

Я работаю на сервере xmlrpc, который циклически выполняет определенные задачи. Я использую скручен как ядро ​​службы XmlRpc но я бег в небольшую проблему:Многопроцессорная обработка Python с помощью скрученного реактора

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 

Как я должен идти о присоединении этих два процесса таким образом, чтобы их соответствующие объединения не блокирует?

(я очень смущен «присоединиться». Почему это блок, и я гугле, но не может найти много полезной объяснения к использованию соединения. Может кто-нибудь объяснить мне это?)

Привет

ответ

11

Вам действительно нужно запустить Twisted в отдельном процессе? Это выглядит довольно необычно для меня.

Постарайтесь подумать о реакторе Twisted в качестве основного цикла - и повесить все, что вам нужно, вместо того, чтобы пытаться запустить Twisted в качестве фоновой задачи.

Более обычным способом выполнения такого рода операций было бы использовать файл .callLater Twisted или добавить объект LoopingCall к реактору.

например.

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 man thx много, поэтому мне нужно точно. Откуда вы узнали о LoopingCall? Вот почему я ненавижу скручивание - документации недостаточно, с одной стороны, в то время как API-интерфейсы настолько велики, что вы склонны игнорировать важные биты. – 2009-09-04 18:49:32

+0

Я знаю, что вы имеете в виду - Twisted может быть сложно узнать, но как только вы получите идею, она отлично работает! Книга O'Reilly довольно старая, но она очень хорошо объясняет, поэтому я рекомендую получить ее копию, если вы собираетесь делать больше с Twisted. –

+1

Я рекомендую подписаться на их список рассылки. Если вы прочтете достаточно ответов от гуру, некоторые из них начинают вставлять * мозг-осмос *. – DrBloodmoney

3

Эй asdvawev - .join() в многопроцессорной работает точно так же, как .join() в резьбе - это блокирующий вызов основной поток бежит ждать работника, чтобы закрыть. Если рабочий никогда не выключается, то .join() никогда не вернется. Например:

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

Вызов запуска на этом означает, что join() никогда не вернется. Как правило, чтобы не допустить этого я буду использовать Event() объект передается в дочерний процесс, чтобы позволить мне сигнал ребенка, когда для выхода:

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) 

В качестве альтернативы, если ваша работа заключена в очереди - вы можете просто чтобы дочерний процесс работал в очереди, пока он не встретит сторожевой (обычно это не запись в очереди), а затем выключится.

Оба эти предложения означают, что перед вызовом .join() вы можете отправить установленное событие или вставить дозорный сигнал и когда вызывается функция join(), процесс завершит текущую задачу и затем выйдет правильно.