Python 语法精炼19
异常
异常(Exception)是程序运行时出现的错误事件,它会中断正常执行流程,并转入异常处理机制。
例如:
1 | print(10 / 0) # ZeroDivisionError |
输出:
1 | ZeroDivisionError: division by zero |
程序遇到错误时,Python 会自动创建一个异常对象并抛出(raise),如果没有被捕获(handled),程序就会终止。
基本结构
Python 的异常处理使用 try、except、else、finally 四个关键字。
1 | try: |
📘 示例:
1 | try: |
✅ 输出举例:
1 | 请输入数字:0 |
传播机制
当异常发生时:
- Python 从当前
try块开始查找匹配的except; - 如果当前函数没有处理,异常会沿调用栈向上传递;
- 若直到顶层都未处理 → 程序终止并打印 Traceback。
📘 示例:
1 | def f1(): |
输出:
1 | 捕获异常: 出错啦! |
捕获异常
捕获特定异常
1 | try: |
捕获多个异常
1 | try: |
捕获所有异常
1 | try: |
注意:Exception 是所有内建异常的父类(除了系统级,如 KeyboardInterrupt)。
不捕获,只查看异常信息
1 | import traceback |
抛出异常
有时你需要主动触发异常,而不是等错误发生:
1 | def divide(a, b): |
raise 会立即中断函数执行,并抛出指定异常对象。
自定义异常类
所有自定义异常类都应继承自 Exception 或其子类。
1 | class MyError(Exception): |
输出:
1 | 捕获到: 自定义异常发生! |
异常链
异常链是指在处理一个异常时又引发另一个异常,Python 会自动或显式地保留原始异常的上下文,形成“异常链”。
隐式异常链
当 except 块中又抛出新的异常时,Python 自动建立链条(__context__)。
1 | try: |
输出:
1 | Traceback (most recent call last): |
这就是隐式异常链:第二个异常的 __context__ 指向第一个异常。
显式异常链
可以用 raise ... from ... 显式指定异常链:
1 | try: |
输出:
1 | ValueError: 新异常 |
from e 明确告诉解释器:ValueError 是由 ZeroDivisionError 直接导致的。
断开异常链
有时不想显示前一个异常,可以用 from None:
1 | try: |
输出:
1 | ValueError: 忽略原异常 |
这在封装库时非常常见,用于隐藏底层细节。
异常对象
每个异常对象都有一些有用的属性:
| 属性 | 含义 |
|---|---|
args |
异常的参数元组 |
__cause__ |
显式异常链的原因 |
__context__ |
隐式异常链的原始异常 |
__traceback__ |
traceback 对象(堆栈信息) |
📘 示例:
1 | try: |
finally 与 else
finally
finally 子句无论是否出错都会执行,常用于清理资源:
1 | try: |
else
else 仅在 try 块未发生异常 时执行:
1 | try: |
输出:
1 | 计算中... |
常见问题
| 陷阱 | 说明 |
|---|---|
| 捕获太宽泛 | except Exception: 会吞掉不必要的错误 |
| 忘记 re-raise | 处理后不重新抛出会隐藏问题 |
滥用 from None |
会导致调试困难 |
不使用 finally |
导致资源未释放 |
总结表
| 概念 | 说明 | 关键点 |
|---|---|---|
try-except |
捕获异常 | 可有多个 except |
else |
无异常时执行 | 放在 except 后 |
finally |
始终执行 | 清理资源 |
raise |
主动抛异常 | 可指定异常对象 |
from |
指定异常链 | raise NewError from OldError |
| 隐式链 | except 中又抛异常 | 自动建立 __context__ |
| 显式链 | from e |
建立 __cause__ |
| 断链 | from None |
隐藏原异常 |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Telason!
