【问题标题】:Understanding Exception Handling in Python了解 Python 中的异常处理
【发布时间】:2015-02-08 02:30:34
【问题描述】:

我有两个关于异常处理的问题。

Q1) 我有点不确定else 中的操作何时将在异常处理中执行。我不确定何时会执行 else 块,这不会出现在下面的代码中:

def attempt_float(SecPrice,diffprice):
    try:
        return float(SecPrice)
    except:
        return diffprice
    else: 
        print "Did we succeed?"

print attempt_float('7','3') 

Q2) 当我运行以下代码时:

def attempt_float(SecPrice,diffprice):
    try:
        return float(SecPrice)
    except:
        return diffprice
    else: 
        print "Did we succeed?"
    finally:
        print "Yasdsdsa"

print attempt_float('7','3')

我不清楚为什么输出是:

Yasdsdsa
7.0

【问题讨论】:

  • 你返回try,所以你从来没有打过else
  • Python try-else 的可能重复项

标签: python function exception exception-handling


【解决方案1】:

当 Python 在函数中遇到返回语句时,它会立即从函数中返回(退出)。这意味着当你这样做时:

try:
    return float(SecPrice)
...
else: 
    print "Did we succeed?"

"Did we succeed?" 永远不会被打印,因为您在 try: 块中返回,从而跳过了 else: 块的执行。


但是,您的第二个代码段不同,因为您使用了 finally: 块。 finally: 块内的代码总是执行,无论是否引发异常、从函数返回等。这是为了确保任何重要的清理代码(即释放资源)总是被执行,不会被意外跳过。

您可以在here 的文档中阅读有关此行为的信息:

return 使用finally 将控制权从try 语句中传递出去时 子句,finally 子句在真正离开之前执行 功能。

还有here:

returnbreakcontinue 语句在try 中执行时 try...finally 语句的套件,finally 子句也是 “在出去的路上”执行。


至于为什么输出是:

Yasdsdsa
7.0

而不是:

7.0
Yasdsdsa

答案是 print "Yasdsdsa" 行在 Python 能够打印 7.0attempt_float 的返回值)之前在 finally: 块中执行。简单来说,Python的执行路径是:

  1. 返回float(SecPrice)
  2. 运行finally: 块。
  3. 使用print attempt_float('7','3') 行恢复正常执行并打印7.0

【讨论】:

  • 谢谢。我主要对为什么输出是这个顺序感到困惑:Yasdsdsa 7.0 而不是相反。
【解决方案2】:

在第一种情况下,您在try 内返回,因此您永远不会点击else 语句。

在第二个中,无论try 如何退出,都会执行finally。来自python docs

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

这是执行顺序的一个很好的例子:

>>> def divide(x, y):
...     try:
...         result = x / y
...     except ZeroDivisionError:
...         print "division by zero!"
...     else:
...         print "result is", result
...     finally:
...         print "executing finally clause"
...
>>> divide(2, 1)
result is 2
executing finally clause
>>> divide(2, 0)
division by zero!
executing finally clause
>>> divide("2", "1")
executing finally clause

请务必阅读有关异常的文档!

【讨论】:

  • 谢谢。如果finally 只执行“在路上”,为什么输出是这个顺序:Yasdsdsa 7.0 而不是相反。
  • 因为你正在打印来自attempt_float的返回值,但是在它返回之前,finally块被执行了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多