直接 raise Exception 不够用,因业务错误类型混杂导致调用方难以精准区分;应定义继承 Exception 的自定义异常类,如 InsufficientBalanceError,包含 error_code、user_id 等字段,支持类型捕获与结构化处理。

为什么直接 raise Exception 不够用
业务逻辑里抛出 Exception 或 ValueError 会让调用方难区分错误类型,比如用户余额不足和订单重复提交都抛 ValueError,上层只能靠字符串匹配判断,一改提示语就崩。自定义异常类能通过类型精准捕获,也方便后续加字段(如错误码、trace_id)。
继承 Exception 并添加业务字段的写法
不要只写空类,至少带上 error_code 和 message 字段,方便日志和 API 返回统一处理:
class InsufficientBalanceError(Exception):
def __init__(self, user_id: int, amount: float, balance: float):
self.error_code = "BALANCE_INSUFFICIENT"
self.user_id = user_id
self.amount = amount
self.balance = balance
self.message = f"User {user_id} has balance {balance}, but needs {amount}"
super().__init__(self.message)
- 构造函数里把关键业务参数存为实例属性,别只拼在 message 里
- 所有字段名用小写+下划线,和 Python 标准库风格一致
- 避免在
__init__里做耗时操作(如查数据库),异常类要轻量
在 try/except 中按类型捕获而非字符串匹配
用类型捕获才能真正解耦——上游不用关心错误提示怎么写,只管“这类错该怎么兜底”:
SkillSub Pro - Python 题解与代码注释双功能技能功能概述SkillSub Pro - Python 题解与代码注释双功能技能是一项面向实际任务的技能,主要用于SkillSub Pro 是一个 Python 题解生成与代码注释的 双功能合体技能 ,专为学生、算法学习者和开发者设计;✅ 一个技能,两种用途 :;核心要点📝 题解模式 :输入题目/题号,自动生成完整 Python 题解(含详细注释、解题思路、复杂度分析);💬 注释模式 :输入 Python 代码,自动添加详细中。它将相关步骤、
try:
charge_user(user_id, amount)
except InsufficientBalanceError as e:
send_sms_alert(e.user_id, e.balance)
record_metric("balance_error", user_id=e.user_id)
except InvalidOrderError as e:
rollback_order(e.order_id)
- 每个 except 块对应一种明确的业务恢复策略,不是统一打日志完事
- 不要写
except Exception:吞掉所有异常,会掩盖本该暴露的 bug - 如果多个异常要走同一处理逻辑,用元组
except (AError, BError):,别重复写块
如何组织大量自定义异常类
项目一多,异常类容易散落在各模块里,建议按领域建包,再用 __all__ 显式导出:
立即学习“Python免费学习笔记(深入)”;
# exceptions/__init__.py from .payment import InsufficientBalanceError, InvalidCardError from .order import InvalidOrderError, OrderAlreadyPaidError <p><strong>all</strong> = [ "InsufficientBalanceError", "InvalidCardError", "InvalidOrderError", "OrderAlreadyPaidError", ]
- 避免在异常类里 import 其他业务模块,防止循环依赖
- 异常类文件名用小写,如
payment.py,类名用大驼峰 - 测试时直接
isinstance(e, InsufficientBalanceError)比检查e.__class__.__name__更可靠
最易被忽略的是异常类的序列化问题:如果要用 JSON 传给下游服务,得重写 __dict__ 或加 to_dict() 方法,否则默认只序列化 message 字符串。

















