假设我使用生成器来处理向数据库中添加信息的过程; 我使用它来存储网络接收的信息,并且通过使用生成器,我可以在每次实际接收数据时高效地执行此操作,否则可以执行其他操作。
因此,我的生成器首先打开一个数据库连接,每当您向它发送内容时,它都会添加一行:
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)
一切都很好。 每次我.close()我的数据都会插入一行。
但是,如果我的数据库是事务性的怎么办? 当将数据提交到数据库时,如何向该生成器发出信号? 以及何时中止交易? 而且,它保持着到数据库的开放连接,也许我有时希望它关闭该连接以回收资源。
这就是.close()方法出现的地方; 使用GeneratorExit,我可以在该方法中引发异常,以发出某些信号:
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()
生成器上的.close()方法基本上执行相同的操作; 它使用GeneratorExit异常与.throw()相结合来关闭正在运行的发电机。
所有这些都是协程如何工作的重要基础。 协程本质上是生成器,还有一些其他语法使编写协程更加容易和清晰。 但是在幕后,它们仍然建立在相同的产量和收益率之上。 而且,当您并行运行多个协程时,您需要一种方法来在其中一个协程失败时干净地退出这些协程。