finally块中的break语句吞下异常

Tim*_*imO 21 python

考虑:

def raiseMe( text="Test error" ):
    raise Exception( text )

def break_in_finally_test():
    for i in range(5):
        if i==2:
            try:
                raiseMe()
            except:
                raise
            else:
                print "succeeded!"
            finally:
                print "testing this!"
                break

if __name__=='__main__':
    break_in_finally_test()
Run Code Online (Sandbox Code Playgroud)

我希望看到Exception( "Test error" )被提升,但只打印"测试这个".当然,目的是raiseMe()只召唤一次,无论我们是否成功 - 但如果它引起异常,我本来想看到它!

为什么break会吞下我明确提出的异常?

M.T*_*M.T 33

来自https://docs.python.org/2.7/reference/compound_stmts.html#finally:

如果finally存在,则指定'cleanup'处理程序.
执行try子句,包括任何except和else子句.如果
任何子句中发生异常但未处理,则会临时保存该异常.
finally子句被执行.如果存在已保存的异常,则会
在finally子句的末尾重新引发异常.如果finally子句引发
另一个异常或执行return或break语句,
则丢弃已保存的异常

这也反映了PEP341try...finally之前的声明所预期的行为:

这是一个除了finally块之外的尝试看起来像PEP341之前的情况:

try:
    try:
        raiseMe()
    except:
        raise
finally:
    #here is where cleanup is supposed to happen before raising error
    break
    #after finally code: raise error
Run Code Online (Sandbox Code Playgroud)

由于错误的发生从未在finally块中发生,因此从未实际提出过.

为了保持与Python <= 2.4的向后兼容性,必须以这种方式完成.

  • 好的,所以___记录.但我不得不说我仍然觉得这种行为真的很令人惊讶(与大多数python行为不同,这通常是如此直观).我的感觉是,例外应该"胜过"回归或破坏...... (2认同)

小智 5

从文档错误处理文档:

在离开try语句之前总是执行finally子句,无论是否发生了异常.

永远不会引发异常,因为在try语句被完全评估之前中断了.