核心篇 · Core
lv.2 核心
kp-015
异常处理
1. 一句话定义
异常是运行期错误的对象化:try/except 捕获并处理,raise 抛出,finally 兜底清理;Python 文化崇尚 EAFP(先做,出错再说),异常是正常控制流的一部分而非羞耻。
2. 为什么重要
错误处理质量区分"能跑"与"可靠"。Python 没有受检异常,正确粒度的 try/except 与自定义异常层次是 API 设计的核心部分。
3. 前置知识
kp-007(函数)、kp-010(dict 访问的错误路径)。
4. 核心概念
python
try:
risky()
except ValueError as e: # 捕获特定异常并绑定
log(e)
except (KeyError, TypeError): # 多类型
pass
else:
print("try 内没抛错才执行") # 放"成功路径"代码,缩小 try 范围
finally:
print("无论如何都执行") # 清理;资源清理优先用 with(kp-025)- 异常层次:
BaseException→Exception→ 各种具体异常;捕获要写到具体类型,裸except:会吞KeyboardInterrupt/SystemExit(应至少写except Exception)。 - raise:
raise XxxError("msg") from original_err(异常链,保留因果)。
5. 原理与机制
异常即对象:try/except 依据异常类的继承关系匹配——except ValueError 能捕获 UnicodeDecodeError(其子类)。利用这一层设计 API:
python
class ConfigError(Exception): pass
class MissingKey(ConfigError): pass
class BadValue(ConfigError): pass
# 调用方可以精细捕获 MissingKey,也可以整体捕获 ConfigErrorEAFP vs LBYL:
python
# LBYL(先看再拿):两次查找 + 竞态窗口
if "k" in d:
v = d["k"]
# EAFP(Pythonic):一次查找,失败路径交给异常
try:
v = d["k"]
except KeyError:
v = default6. 关键事实(模型/图示)
text
raise ──► 沿调用栈向上传播 ──► 最近匹配的 except ──► finally 保证执行
└── 无人捕获 ──► 解释器打印 traceback,进程退出7. 直观类比
异常像电梯报警:不出事时完全不付出代价(对比"每层都探头检查"的 LBYL);出事时直接冲到最近的能处理这层楼的保安(except)手里,而 finally 是"无论有没有报警,出门都要刷卡"。
8. 实例与案例
python
# 解析外部数据:转换与业务校验分层
def parse_int(s):
try:
return int(s)
except (TypeError, ValueError):
raise BadValue(f"不是整数: {s!r}") from Nonefrom None 抑制原始 traceback,让报错信息干净聚焦。
9. 常见误区
- 裸
except:或except Exception: pass—— 吞掉一切错误让 bug 隐身;要捕获就处理、要处理就具体。 - try 范围过大 —— try 只包"可能抛错的那一行",成功逻辑放
else,否则不知道错来自哪。 - 用异常做常规分支(如循环里抛异常控制结束)—— EAFP 不等于滥用;每秒成千上万次的热路径用返回哨兵或
dict.get。 - 忘记异常链 —— 在 except 里再 raise 时用
from e,否则原始现场丢失。
10. 自测题
except:与except Exception:的区别?为什么前者危险?try/else中 else 什么时候执行?为什么把代码放 try 外面更好?raise A() from B的作用?
参考答案
except:匹配包括 SystemExit/KeyboardInterrupt 在内的所有异常(BaseException 级),会吞掉用户 Ctrl+C 与退出信号;except Exception:不含系统级异常。- try 体未抛任何异常时;缩小 try 范围,让 traceback 更准确、意图更清晰。
- 显式建立异常因果链:新异常的
__cause__指向 B,traceback 显示 "The above exception was..."。
11. 与其他知识点的关系
12. 延伸阅读
- Python 官方教程 §8 Errors and Exceptions
- 《Effective Python》Item:用异常表达预期错误