【问题标题】:Python: try...except...finally clauses in generatorsPython:try...except...finally 生成器中的子句
【发布时间】:2025-11-23 11:55:02
【问题描述】:

代码

def gen():
    try:
        for i in range(5):
            yield i
    except Exception as e:
        print('Caught: ' + str(e))
    finally:
        print('I am done')

for x in gen():
    print(x)
    if x == 2:
        raise Exception('Catch me?')

输出

0
1
2
I am done
Traceback (most recent call last):
  File "test.py", line 13, in <module>
    raise Exception('Catch me?')
Exception: Catch me?

问题

为什么代码执行finally子句而不执行except子句?

请结合参考资料进行说明。

【问题讨论】:

  • 您在gen() 函数之外引发异常,因此它不会捕获它。并且finally 总是被执行。
  • 因为finally 每次无论代码是否失败都会执行(就像清理一样),并且您在生成器外部而不是内部引发了异常,所以它不知道它
  • 试试 - g = gen(); g.throw(ValueError) .

标签: python exception generator


【解决方案1】:

生成器函数的主体只会在for 循环的迭代之间 运行。也就是说,for 循环的含义类似于:

  1. 从生成器获取下一个值
  2. 运行循环体
  3. 返回步骤 1

只有第 1 步涉及在生成器函数中实际运行代码。由于生成器函数中try 块内的代码不会引发任何异常,因此except 子句没有什么可捕获的。 finally 子句执行是因为它总是执行(这就是 finally 的用途)。

在生成器上使用循环并不意味着整个循环体在生成器函数“内部”运行。这只是意味着一次从生成器中获取一个值,直到它耗尽。循环体仍然在自己的范围内执行,与生成器函数的范围分开。

【讨论】:

  • 因此,如果在具有finally 子句的生成器之外引发异常,那么该子句何时运行?如果主函数使用多个生成器,每个生成器都有一个finally 子句怎么办?它们按什么顺序执行?
  • @Cyker:如果这是你的问题,你应该编辑你的问题来问它。 finally 子句在其try 块中的代码完成时执行。如果您的生成器在 try 块中挂起,那么它的 finally 子句将在生成器关闭之前不会执行(如果有的话)。