当协程引发异常时会发生什么?

时间:2013-03-12 21:00:17

标签: python coroutine

我不确定以下代码中到底发生了什么:

def coroutine():
    lst = []
    try:
        while True:
            item = (yield lst)
            if item == 3:
                raise ValueError
            print('append {}'.format(item))
            lst.append(item)
    except GeneratorExit:
        print('GeneratorExit')

crt = coroutine()

next(crt)
print(crt.send(1))
print(crt.send(2))

try:
    print(crt.send(3))
except ValueError:
    pass

print(crt.send(4))

输出:

append 1
[1]
append 2
[1, 2]

Traceback (most recent call last):
  File "D:\Documents and Settings\Brecht\Desktop\crt.py", line 25, in <module>
    print(crt.send(4))
StopIteration

当使用调试器逐步执行代码时,在raise ValueError上,执行跳转到except GeneratorExit:,但不执行此except子句的主体(不打印'GeneratorExit')。为什么不呢?

除此之外,我不认为在抛出异常之后我可以以任何方式恢复协同程序吗?是否有任何特殊原因不允许这样做?这至少在我的特定用例中是有用的:)

1 个答案:

答案 0 :(得分:4)

当您抛出异常时,代码流始终被中断。一旦在其中抛出异常,就无法恢复中断的生成器。

来自PEP 342 (Coroutines via Enhanced Generators)

  

next()方法一样,send()方法返回下一个值       由生成器 - 迭代器产生,或者如果是,则引发StopIteration       发电机正常退出,或已经退出。如果发电机       引发未捕获的异常,它会传播到send()的调用者。

至于调试器跳转到except行:你刚刚抛出一个异常,解释器正在测试异常是否被该行捕获。因为它只会捕获GeneratorExit,所以生成器会在此时退出。