2008-09-17 15 views
29

Ich habe Probleme bei der Entwicklung eines Reverse-Proxy in Twisted. Es funktioniert, aber es scheint übermäßig komplex und verschachtelt. So viel fühlt sich an wie Voodoo.Asynchrone Programmierung in Python Twisted

Gibt es einfache, solide Beispiele für asynchrone Programmstruktur im Internet oder in Büchern? Eine Art Best-Practice-Leitfaden? Wenn ich mein Programm vervollständige, würde ich gerne in der Lage sein, die Struktur auf irgendeine Weise zu sehen, ohne auf eine Schüssel Spaghetti zu schauen.

+5

Ich hoffe, Sie haben mehr Glück mit twisted. Es ist derzeit eines meiner Lieblings-Frameworks. – Dustin

Antwort

0

Wenn Sie nicht versuchen, verdreht zu verwenden, gab es eine gute Anleitung, die ich vor einiger Zeit benutzt habe. Hier ist die link to it.

64

Twisted enthält eine large number of examples. Eine davon, die "evolution of Finger" tutorial, enthält eine gründliche Erklärung, wie ein asynchrones Programm von einem sehr kleinen Kernel zu einem komplexen System mit vielen beweglichen Teilen wächst. Eine andere, die für Sie von Interesse sein könnte, ist das Tutorial über einfach writing servers.

Das Wichtigste im Auge zu behalten über Verdreht, oder auch andere asynchronen Networking-Bibliotheken (wie asyncore, MINA oder ACE), ist, dass der Code nur dann aufgerufen wird, wenn etwas passiert. Der Teil, den ich am häufigsten als "Voodoo" hörte, ist die Verwaltung von Rückrufen: zum Beispiel Deferred. Wenn Sie daran gewöhnt sind, Code zu schreiben, der in einer geraden Linie läuft und nur Funktionen aufruft, die sofort mit Ergebnissen zurückkommen, könnte die Idee, auf etwas zu warten, um Sie zurückzurufen, verwirrend sein. Aber es gibt nichts Magisches, kein "Voodoo" über Rückrufe. Auf der untersten Ebene wird der Reaktor nur sitzen herum und wartet auf einen von einer kleinen Anzahl von Dingen passieren:

  1. Daten treffen auf eine Verbindung (es dataReceived über ein Protokoll nennen)
  2. Zeit ist vergangen (es wird eine mit registrierte Funktion aufrufen).
  3. Eine Verbindung wurde angenommen (sie ruft buildProtocol auf einer Fabrik an, die mit einer listenXXX oder connectXXX Funktion registriert ist).
  4. Eine Verbindung fallen gelassen wurde (es connectionLost auf das entsprechende Protokoll nennen)

Jedes asynchrone Programm beginnt mit ein paar dieser Ereignisse Einhaken und dann in den Reaktor Auftakt zu warten, bis sie passieren. Natürlich führen Ereignisse, die passieren, zu mehr Ereignissen, die verbunden oder getrennt werden, und so geht Ihr Programm auf seinen fröhlichen Weg. Darüber hinaus gibt es nichts besonderes an der asynchronen Programmstruktur, die interessant oder besonders ist. Event-Handler und Callbacks sind nur Objekte, und Ihr Code wird auf die übliche Weise ausgeführt.

Hier ist eine einfache "ereignisgesteuerte Engine", die Ihnen zeigt, wie einfach dieser Prozess ist.

# Engine 
import time 
class SimplestReactor(object): 
    def __init__(self): 
     self.events = [] 
     self.stopped = False 

    def do(self, something): 
     self.events.append(something) 

    def run(self): 
     while not self.stopped: 
      time.sleep(0.1) 
      if self.events: 
       thisTurn = self.events.pop(0) 
       thisTurn() 

    def stop(self): 
     self.stopped = True 

reactor = SimplestReactor() 

# Application  
def thing1(): 
    print 'Doing thing 1' 
    reactor.do(thing2) 
    reactor.do(thing3) 

def thing2(): 
    print 'Doing thing 2' 

def thing3(): 
    print 'Doing thing 3: and stopping' 
    reactor.stop() 

reactor.do(thing1) 
print 'Running' 
reactor.run() 
print 'Done!' 

Im Kern-Bibliotheken wie Verdreht, ist die Funktion in der Hauptschleife nicht sleep, aber ein Betriebssystem-Aufruf wie select() oder poll(), wie the Python select module wie durch ein Modul belichtet. Ich sage "like" select, weil dies eine API ist, die zwischen den Plattformen sehr unterschiedlich ist, und fast jedes GUI-Toolkit hat seine eigene Version. Twisted bietet derzeit eine abstrakte Schnittstelle zu 14 verschiedenen Variationen zu diesem Thema. Die übliche Sache, die eine solche API bietet, ist eine Möglichkeit zu sagen: "Hier sind eine Liste von Ereignissen, auf die ich warte. Geh schlafen, bis einer von ihnen passiert, dann wache auf und sag mir, welcher von ihnen es war."