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:
- Daten treffen auf eine Verbindung (es
dataReceived
über ein Protokoll nennen)
- Zeit ist vergangen (es wird eine mit registrierte Funktion aufrufen).
- Eine Verbindung wurde angenommen (sie ruft
buildProtocol
auf einer Fabrik an, die mit einer listenXXX
oder connectXXX
Funktion registriert ist).
- 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."
Ich hoffe, Sie haben mehr Glück mit twisted. Es ist derzeit eines meiner Lieblings-Frameworks. – Dustin