【问题标题】:Why doesn't `finally: return` propagate an unhandled exception? [duplicate]为什么`finally: return` 不传播未处理的异常? [复制]
【发布时间】:2016-10-31 21:05:44
【问题描述】:

为什么函数不引发异常?它显然没有被抓住。

def f():
    try:
        raise Exception
    finally:
        return "ok"

print(f())  # ok

【问题讨论】:

  • 您还能期待什么?您可以返回或引发异常,但不能同时返回。您明确要求退货,因此不会引发异常。

标签: python python-3.x exception-handling


【解决方案1】:

documentation 说:

finally 子句总是在离开try 语句之前执行,无论是否发生异常。当try 子句中发生异常并且未被except 子句处理(或者它已发生在exceptelse 子句中)时,它会在finally 子句之后重新引发已被执行。

在您的情况下,尚未处理异常,因此应在 finally 子句之后重新引发,但由于您从 finally 子句返回,因此永远不会重新引发异常。

【讨论】:

    【解决方案2】:

    来自documentation

    finally 子句总是执行 在离开 try 语句之前,无论是否发生异常。 [...] 当 try 语句的任何其他子句通过 break、continue 或 return 语句 离开时,finally 子句也“在退出时”执行

    这意味着,在函数中,finally 子句将始终是返回的子句。即使没有异常发生:

    def f():
        try:
            return 'OK'
        finally:
            return 'Finally'
    
    f() # returns 'Finally'
    

    【讨论】:

      【解决方案3】:

      这在the documentation中有明确解释:

      如果任一子句发生异常且未处理,则暂时保存该异常。 finally 子句被执行。 [..] 如果finally 子句执行returnbreak 语句,保存的异常将被丢弃

      【讨论】:

      • 这就是我要找的报价,+1。
      【解决方案4】:

      来自docs

      finally 子句总是在离开 try 语句之前执行。

      @deceze 在他的answer

      中引用了更相关的部分

      该函数返回finally 子句中的字符串,并且不会引发异常,因为它返回,并且会打印什么。

      如果你尝试执行:

      >>> try:
      ...     raise Exception
      ... finally:
      ...     print('yes')
      ... 
      yes
      Traceback (most recent call last):
        File "<stdin>", line 2, in <module>
      Exception
      

      然后如您所见,“yes”被打印出来,并且在打印语句之后抛出异常。

      【讨论】:

        猜你喜欢
        • 2011-03-14
        • 2015-01-17
        • 2020-08-16
        • 1970-01-01
        • 2011-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-17
        相关资源
        最近更新 更多