在 Python 中,try...except...finally 块(通常还可以包含 else)提供了一种强大而灵活的方式来处理程序运行期间可能发生的异常(错误)。其执行逻辑遵循一套明确的规则,确保代码的健壮性和资源的正确管理。
核心原则是:finally 子句中的代码无论如何都会执行。 这使得它成为执行清理操作(如关闭文件或数据库连接)的理想场所。
下面我们通过不同的场景来详细分解其执行逻辑:
场景一:try 块中没有发生异常
- 执行
try块:程序首先执行try块中的所有代码。 - 执行
else块:由于没有异常发生,程序会接着执行else块中的代码。 - 执行
finally块:最后,执行finally块中的代码。
示例代码:
try:
print("1. try 块开始执行")
result = 10 / 2
print("2. try 块成功执行完毕")
except ZeroDivisionError:
print("except 块:出现除零错误!")
else:
print(f"3. else 块:没有异常发生,计算结果为 {result}")
finally:
print("4. finally 块:清理工作...")
# 输出:
# 1. try 块开始执行
# 2. try 块成功执行完毕
# 3. else 块:没有异常发生,计算结果为 5.0
# 4. finally 块:清理工作...
场景二:try 块中发生异常,且被 except 捕获
- 执行
try块:程序从try块开始执行,直到遇到引发异常的那一行。 - 中断
try块:try块中发生异常后的剩余代码将不会被执行。 - 匹配并执行
except块:程序会寻找能够匹配所发生异常的except子句,并执行该子句中的代码。 - 跳过
else块:因为发生了异常,else块将被完全跳过。 - 执行
finally块:在except块执行完毕后,finally块中的代码将被执行。
示例代码:
try:
print("1. try 块开始执行")
result = 10 / 0 # 发生异常
print("这行代码不会被执行")
except ZeroDivisionError:
print("2. except 块:捕获到除零错误!")
else:
print("else 块:这段代码不会执行")
finally:
print("3. finally 块:清理工作...")
# 输出:
# 1. try 块开始执行
# 2. except 块:捕获到除零错误!
# 3. finally 块:清理工作...
场景三:try 块中发生异常,但没有被 except 捕获
- 执行
try块:程序在try块中执行直到发生异常。 - 中断
try块:try块中发生异常后的剩余代码不会被执行。 - 执行
finally块:在将异常向上传播之前,程序会先执行finally块中的代码。 - 传播异常:
finally块执行完毕后,由于没有找到匹配的except子句,异常会向上一层调用栈传播。如果上层也没有处理,程序最终会崩溃并显示错误信息。
示例代码:
try:
print("1. try 块开始执行")
result = 10 / 0 # 发生 ZeroDivisionError
except ValueError: # 不能匹配 ZeroDivisionError
print("except 块:捕获到值错误!")
finally:
print("2. finally 块:清理工作...")
# 输出:
# 1. try 块开始执行
# 2. finally 块:清理工作...
# Traceback (most recent call last):
# File "your_script.py", line 3, in <module>
# result = 10 / 0
# ZeroDivisionError: division by zero
return 语句与 finally 的交互
这是一个需要特别注意的复杂情况。如果 try、except 或 else 块中有 return 语句,finally 块依然会在函数真正返回之前执行。
- 如果
finally块中没有return:try/except/else中的return语句会先计算好返回值,然后去执行finally块,最后再返回之前计算好的那个值。 - 如果
finally块中也有return:那么程序将直接从finally块返回,并忽略try/except/else中已经执行过的return语句。 这通常被认为是不好的编程实践,因为它会使代码逻辑变得混乱,应尽量避免。
finally 中没有 return 的示例:
def check_value():
try:
print("try 块")
return "从 try 返回"
finally:
print("finally 块执行")
print(check_value())
# 输出:
# try 块
# finally 块执行
# 从 try 返回
总结
| 场景 | try | except | else | finally | 最终结果 |
|---|---|---|---|---|---|
| 无异常 | 执行 | 跳过 | 执行 | 执行 | 正常执行 |
| 有异常,被捕获 | 执行至异常处 | 执行 | 跳过 | 执行 | 异常被处理,继续执行 |
| 有异常,未捕获 | 执行至异常处 | 跳过 | 跳过 | 执行 | 异常向上传播 |
1037

被折叠的 条评论
为什么被折叠?



