Python 错误处理
Python 的 try/except 异常处理机制、常见异常类型与最佳实践。
#type / concept
#status / growing
#resource / python
#tech / lang / python
[!info] related notes
- 所属 MOC: python-moc
- 前置概念: python数据类型与数据结构, python函数与装饰器
- 并列概念: Python 字典 (dict)
- 关系笔记: python
Python 错误处理
一句话定义
Python 用 try/except 捕获和处理运行时异常,防止程序因意外错误崩溃。
核心机制
基本语法
try:
# 可能出错的代码
result = 10 / 0
except ZeroDivisionError:
# 处理特定异常
print("不能除以零")
完整结构
try:
data = json.loads('{"name": "Alice"}')
except json.JSONDecodeError as e:
# as e 可以拿到错误详情
print(f"JSON 解析失败: {e}")
except KeyError as e:
print(f"缺少字段: {e}")
else:
# 没有异常时执行
print("解析成功")
finally:
# 无论如何都会执行(清理资源)
print("处理完毕")
捕获多种异常
try:
value = some_dict["key"]
except (KeyError, TypeError) as e:
# 同时捕获多种异常
print(f"读取失败: {e}")
不推荐的写法
try:
do_something()
except:
# ❌ 裸 except 会捕获所有异常,包括 KeyboardInterrupt
# 隐藏了真正的错误,调试困难
pass
常见异常类型
| 异常 | 触发场景 | 示例 |
|---|---|---|
KeyError | 字典中 key 不存在 | {}["missing"] |
TypeError | 类型不匹配 | "hello" + 42 |
ValueError | 值不合法 | int("abc") |
AttributeError | 对象没有该属性 | "hello".fake_method() |
IndexError | 列表索引越界 | [1,2,3][10] |
FileNotFoundError | 文件不存在 | open("nope.txt") |
ZeroDivisionError | 除以零 | 1 / 0 |
ImportError | 模块导入失败 | import nonexistent |
json.JSONDecodeError | JSON 解析失败 | json.loads("not json") |
实战场景
场景 1:安全读取嵌套数据(AI API 响应)
try:
content = response["choices"][0]["delta"]["content"]
except (KeyError, IndexError):
content = None
# 或者用 get 链式访问(更简洁)
content = response.get("choices", [{}])[0].get("delta", {}).get("content")
场景 2:网络请求失败重试
import requests
for attempt in range(3):
try:
r = requests.get("https://api.example.com", timeout=5)
r.raise_for_status() # 4xx/5xx 时抛异常
break
except requests.RequestException as e:
print(f"请求失败 (第{attempt+1}次): {e}")
if attempt == 2:
raise
场景 3:自定义异常
class APIError(Exception):
def __init__(self, status_code, message):
self.status_code = status_code
self.message = message
# 使用
try:
if r.status_code != 200:
raise APIError(r.status_code, "请求失败")
except APIError as e:
print(f"API 错误 {e.status_code}: {e.message}")
边界与易混淆点
except Exceptionvs 裸except:except Exception捕获大部分异常但不包括SystemExit、KeyboardInterrupt;裸except什么都能捕获,不推荐as e不是必须的:如果不需要错误详情,可以省略finally的用途:关闭文件、释放锁、断开连接等清理工作- 异常是有成本的:不要用异常做正常流程控制(EAFP 原则虽好,但高频路径上 try/except 比 if 判断慢)
raise重新抛出:在except块中用raise可以继续传播异常,常用于日志记录后重新抛出