Angenommen, ich benutze einen Generator, um Informationen in eine Datenbank einzufügen; Ich verwende dies, um vom Netzwerk empfangene Informationen zu speichern, und indem ich einen Generator verwende, kann ich dies effizient tun, wann immer ich tatsächlich Daten erhalte, und sonst etwas anderes tun.
Also, mein Generator zunächst eine Datenbankverbindung öffnet, und jedes Mal, wenn es etwas zu senden, wird es eine Zeile hinzufügen:
def add_to_database(connection_string):
db = mydatabaselibrary.connect(connection_string)
cursor = db.cursor()
while True:
row = yield
cursor.execute('INSERT INTO mytable VALUES(?, ?, ?)', row)
Das ist alles schön und gut ist; jedes Mal, wenn ich meine Daten .send()
einfüge, wird eine Zeile eingefügt.
Aber was, wenn meine Datenbank transaktional ist? Wie signalisiere ich diesen Generator, wenn die Daten in die Datenbank übertragen werden sollen? Und wann soll die Transaktion abgebrochen werden? Außerdem hält es eine offene Verbindung zur Datenbank aufrecht, vielleicht möchte ich manchmal, dass es diese Verbindung schließt, um Ressourcen zurückzufordern.
Hier kommt die .throw()
Methode ins Spiel; mit .throw()
kann ich Ausnahmen in diesem Verfahren erhöht bestimmte Umstände zu signalisieren:
def add_to_database(connection_string):
db = mydatabaselibrary.connect(connection_string)
cursor = db.cursor()
try:
while True:
try:
row = yield
cursor.execute('INSERT INTO mytable VALUES(?, ?, ?)', row)
except CommitException:
cursor.execute('COMMIT')
except AbortException:
cursor.execute('ABORT')
finally:
cursor.execute('ABORT')
db.close()
Die .close()
Verfahren an einem Generator funktionieren im Wesentlichen die gleiche Sache; Es verwendet die GeneratorExit
-Ausnahme kombiniert mit .throw()
, um einen laufenden Generator zu schließen.
All dies ist eine wichtige Untermauerung davon, wie coroutines arbeiten; Koroutinen sind im wesentlichen Generatoren, zusammen mit einer zusätzlichen Syntax, um das Schreiben einer Koroutine einfacher und klarer zu machen. Aber unter der Haube sind sie immer noch auf demselben Ertrag gebaut und senden. Und wenn Sie mehrere Coroutinen parallel ausführen, benötigen Sie eine Möglichkeit, diese Korutinen sauber zu verlassen, wenn einer von ihnen fehlgeschlagen ist, um nur ein Beispiel zu nennen.
Kontext: Ich arbeite gerade an einer Generator/Coroutine-Implementierung in PHP und frage mich, ob ich die 'throw()' -Funktionalität mit einbeziehen soll oder nicht. – NikiC
Willst du Generatoren oder Coroutinen? Während Python die beiden zusammenfasst, und Sie die erstere aus letzterem aufbauen können, sind sie anders (wie in einer ganz anderen Liga). – delnan