python - 如何在发电机中检测到它已被外部中断

标签 python exception generator

我有这个生成器:

def gen():
    rounds = 0
    for x in xrange(10):
        rounds += 1
        yield x
    print 'Generator finished (%d rounds)' % (rounds)

如果我正常调用它:

for x in gen():
    pass

我得到了预期的结果:

Generator finished (10 rounds)

但是如果我中断生成器,我什么也得不到:

for x in gen():
    break

我想得到:

Generator interrupted (1 rounds)

是否有可能在生成器本身中检测到它已被外部中断?是否有任何我可以捕获以检测此事件的异常

最佳答案

你不能,因为生成器的默认行为是一直被中断。生成器一直暂停,每次它产生一个值。

换句话说,你对发电机工作原理的理解是错误的。生成器的循环完全不受生成器的控制;它的任务就是生成下一个值,该值会取消暂停代码,直到执行下一个 yield 表达式。

因此,当没有请求下一个值时,生成器将暂停并且无法执行代码来“检测”它没有被请求另一个值。

调用生成器函数时会发生什么:

  • 特别generator iterator object被退回。函数体中没有代码被执行。
  • 生成器迭代器之外的代码 可能会也可能不会将其用作迭代器。每次需要一个新值时,generator_object.next()被称为。
  • .next() 方法被调用时,函数体运行,直到遇到 yield 表达式。函数体暂停,yield 表达式的结果作为 .next() 方法的结果返回。

您可以使用 generator_object.send() 在生成器函数中显式发送消息或引发异常和 generator_object.throw()方法,但在不遍历生成器对象时不会发送此类消息或异常。

可以寻找的一件事是当生成器对象关闭时在您的生成器函数中抛出的GeneratorExit 异常;查看generator_object.close() method :

Raises a GeneratorExit at the point where the generator function was paused

当一个生成器对象被垃圾收集(例如,没有任何东西再引用它)时,generator_object.close() 方法被自动调用:

def gen():
    rounds = 0
    for x in xrange(10):
        rounds += 1
        try:
            yield x
        except GeneratorExit:
            print 'Generator closed early after %d rounds' % rounds
            raise
    print 'Generator finished (%d rounds)' % rounds

演示:

>>> def gen():
...     rounds = 0
...     for x in xrange(10):
...         rounds += 1
...         try:
...             yield x
...         except GeneratorExit:
...             print 'Generator closed early after %d rounds' % rounds
...             raise
...     print 'Generator finished (%d rounds)' % rounds
... 
>>> for i in gen():
...     break
... 
Generator closed early after 1 rounds

这之所以有效,是因为返回的生成器对象仅被 for 循环引用,并且在 for 循环结束时被获取。

关于python - 如何在发电机中检测到它已被外部中断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26057722/

相关文章:

python - 无法 pipenv 从源代码(pypi)安装 confluent-kafka 1.4.0 - 似乎没有解决方法

python - 如何根据 csr 矩阵交叉检查 python 字典列表

Python:生成一个包含 5 列的多值真值表,其中每列可以取一组特定的值

.net - SharpGen 对于 SharpDX 以外的其他项目有用吗?还是我应该使用 SWIG?

python - nos2.main() 详细输出

java - 对事务和锁定的 jpa 考试感到困惑

python - cython 中的异常处理

Java连接Get请求异常处理

javascript - 协程示例

python - 如何展平具有 : primitives data types, 列表和生成器的列表?