【问题标题】:Why doesn't Python 2.7 let me implicitly re-raise an exception after yield?为什么 Python 2.7 不允许我在 yield 后隐式地重新引发异常?
【发布时间】:2014-10-01 02:38:07
【问题描述】:

我注意到 Python 2.7.5 在 except: 块内屈服时出现了一些奇怪的行为:

def generator():
    try:
        raise Exception()
    except:
        yield
        raise

list(generator())

此代码因TypeError: exceptions must be old-style classes or derived from BaseException, not NoneType 而失败

为什么 Python 会这样做,而不是像 yield 不在 raise 之前那样重新引发异常?

(显然 Python 3 已经修复了这个问题,并且该函数会按照您的预期生成一个 [None] 列表。)

(解决方法是将异常存储在变量中:except Exception as e: yield; raise e

【问题讨论】:

  • 任意代码(包括也会引发异常的代码)可以在yieldraise 语句之间执行。我怀疑保留一堆可能引发的未决异常的语义几乎是不可能定义的。
  • @chepner 根本没有,异常可能只是成为 except 块内的隐藏局部变量。如果它在 Python 3 中工作,那么它听起来就像是一个已修复的错误。
  • 异常存储在当前线程的堆栈帧中,但我怀疑它已被清除,因为yield 导致堆栈帧被搁置并且控制返回到驱动迭代的帧.

标签: python python-2.7 generator


【解决方案1】:

这只是 Python 2.x 中的一个错误。根据bug report 的说法,该问题已在 Python 3 中得到修复,但由于向后移植的复杂性,该修复在进入维护模式之前从未达到 2.7:

这在 Python 3 中已修复。我不知道是否值得向后移植 更改,因为可能很难避免也向后移植 异常模型中的不兼容性。

八个月后...

由于 2.7 处于维护状态,因此不会向后移植。

【讨论】:

    猜你喜欢
    • 2012-10-13
    • 2020-05-26
    • 1970-01-01
    • 2011-04-21
    • 2018-05-28
    • 1970-01-01
    • 1970-01-01
    • 2019-07-23
    • 2021-10-04
    相关资源
    最近更新 更多