generator.throw()有什么用? [英] What is generator.throw() good for?

查看:105
本文介绍了generator.throw()有什么用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

PEP 342(通过增强型生成器进行协程)添加了throw()生成器对象的方法,允许调用者在生成器内部 引发异常(就像它是由yield表达式抛出的一样).

PEP 342 (Coroutines via Enhanced Generators) added a throw() method to generator objects, which allows the caller to raise an exception inside the generator (as if it was thrown by the yield expression).

我想知道此功能的用例是什么.

I am wondering what the use cases for this feature are.

推荐答案

假设我使用生成器来处理向数据库中添加信息;我使用它来存储网络接收的信息,并且通过使用生成器,我可以在每次实际接收数据时高效地执行此操作,否则可以执行其他操作.

Let's say I use a generator to handle adding information to a database; I use this to store network-received information, and by using a generator I can do this efficiently whenever I actually receive data, and do other things otherwise.

因此,我的生成器首先打开一个数据库连接,并且每次向它发送内容时,它都会添加一行:

So, my generator first opens a database connection, and every time you send it something, it'll add a row:

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)

一切都很好,很好;每当我.send()我的数据时,它都会插入一行.

That is all fine and well; every time I .send() my data it'll insert a row.

但是如果我的数据库是事务性的怎么办?当将数据提交到数据库时,如何向该生成器发出信号?以及何时中止交易?而且,它保持着到数据库的开放连接,也许我有时希望它关闭该连接以回收资源.

But what if my database is transactional? How do I signal this generator when to commit the data to the database? And when to abort the transaction? Moreover, it is holding an open connection to the database, maybe I sometimes want it to close that connection to reclaim resources.

这是.throw()方法出现的地方;使用.throw(),我可以在该方法中引发异常以表示某些情况:

This is where the .throw() method comes in; with .throw() I can raise exceptions in that method to signal certain circumstances:

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()来关闭正在运行的生成器.

The .close() method on a generator does essentially the same thing; it uses the GeneratorExit exception combined with .throw() to close a running generator.

所有这些都是协程工作方式的重要基础;协程本质上是生成器,还有一些其他语法使编写协程更加容易和清晰.但是在幕后,它们仍然建立在相同的收益和收益上.而且,当您并行运行多个协程时,您需要一种方法,如果其中一个协程失败,则干净地退出这些协程.仅举一个例子.

All this is an important underpinning of how coroutines work; coroutines are essentially generators, together with some additional syntax to make writing a coroutine easier and clearer. But under the hood they are still built on the same yielding, and sending. And when you are running multiple coroutines in parallel, you need a way to cleanly exit those coroutines if one of them has failed, just to name an example.

这篇关于generator.throw()有什么用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆