Diciamo che uso un generatore per gestire l'aggiunta di informazioni a un database; Io lo uso per archiviare le informazioni ricevute dalla rete e, utilizzando un generatore, posso farlo in modo efficiente ogni volta che ricevo effettivamente dati e altre cose.
Quindi, il mio generatore prima apre una connessione al database, e ogni volta che lo si invia qualcosa, sarà aggiungere una riga:
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)
Questo è tutto bene e bene; ogni volta che i miei dati sono .send()
inserirò una riga.
Ma cosa succede se il mio database è transazionale? Come faccio a segnalare questo generatore quando si impegnano i dati nel database? E quando interrompere la transazione? Inoltre, è in possesso di una connessione aperta al database, forse a volte voglio che chiuda quella connessione per recuperare le risorse.
Qui è dove entra il metodo .throw()
; con .throw()
posso alzare eccezioni a tale metodo per segnalare determinate circostanze:
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()
Procedimento .close()
su un generatore fa essenzialmente la stessa cosa; utilizza l'eccezione GeneratorExit
combinata con .throw()
per chiudere un generatore in esecuzione.
Tutto questo è un importante supporto di come coroutines lavoro; le coroutine sono essenzialmente generatori, insieme ad alcune sintassi aggiuntive per rendere più semplice e chiara la scrittura di una coroutine. Ma sotto il cofano sono ancora costruiti sulla stessa resa e invio. E quando si eseguono più coroutine in parallelo, è necessario un modo per uscire in modo pulito da quelle coroutine se uno di essi ha fallito, solo per citarne un esempio.
Contesto: attualmente sto lavorando su un'implementazione di generatore/coroutine in PHP e mi chiedo se dovrei includere o meno la funzionalità 'throw()'. – NikiC
Vuoi generatori o coroutine? Mentre Python confonde i due, e tu puoi costruire il primo da quest'ultimo, sono diversi (come in un campionato completamente diverso). – delnan