判断异常实例类型应使用 isinstance(exc, ValueError),而非 issubclass(type(exc), ValueError);后者冗余且易错,isinstance 语义清晰、支持子类、性能更优。
用
判断异常实例类型,别用
直接说结论:判断一个异常对象是否属于某类(比如
或其子类),该用
,而不是
。后者不仅多此一举,还容易在自定义异常继承链复杂时出错——
的第二个参数必须是类,而你传的是实例的类型,逻辑上就绕了一圈。
常见错误现象:
- 写成
→ 报
- 写成
→ 能运行,但掩盖了类型检查本意,且对带泛型或动态生成的异常类(如某些库的包装异常)可能误判
是专为“实例是否属于某类或其子类”设计的,语义清晰、性能好、兼容所有 Python 版本
异常捕获后拿到的是实例(
),不是类,直接用
最自然
若真要比较类(比如在元编程中预检异常类关系),才轮到
,且两个参数都得是类,例如
在
块里做细粒度判断时,优先用多重
或
有时你 catch 了一个宽泛异常(比如
),又想在内部区分处理逻辑。这时候别在
里堆
,除非有明确理由(如统一日志+分发)。
更推荐写法:
多重
更高效:CPython 在匹配时直接查异常 MRO,不创建中间对象
如果必须统一捕获再分发(比如框架统一异常处理器),用
安全可靠;
多一次
调用,无收益
注意:
支持元组,比嵌套
更简洁
自定义异常继承时,
自动支持 MRO 查找
Python 异常继承遵循标准方法解析顺序(MRO)。只要你的自定义异常正确继承,
就能按预期工作。
立即学习
“
Python免费学习笔记(深入)
”;
Python 3.14.3
微软官方的 Python 扩展,是 VS Code 安装量最高的扩展(209M+)。集成 IntelliSense(通过 Pylance)、调试(通过 Python Debugger)、代码检查、格式化、重构和单元测试等功能。支持 Jupyter Notebook、虚拟环境管理和多 Python 版本切换。
下载
示例:
不需要手动遍历
——
已经做了
避免写
:这只能匹配精确类,不认子类(比如
是
子类,但
判断会失败)
如果用
模拟同类行为,必须写成
,但依然不如
直观安全
真正需要
的场景:检查异常类本身的关系
只有当你手里拿的是「类」,而非「异常实例」时,
才是正确工具。典型场景包括:
插件系统中验证用户注册的异常类是否继承自基类:
测试中断言异常继承结构:
动态构建异常处理策略前,预检类兼容性(如某 SDK 要求传入的 error class 必须是
的子类)
这时候传给
的两个参数都必须是类对象。混入实例(比如
)会立刻报错,而且这个错误往往在运行时才暴露,不利于静态分析和 IDE 提示。
异常类型判断这件事,核心就一条:手上是实例,就用
;手上是类,才轮到
。混淆这两者,多数时候不是技术限制,而是对 Python 类型模型理解偏移了一点点。
isinstanceissubclassValueErrorisinstance(exc, ValueError)issubclass(type(exc), ValueError)issubclassissubclass(exc, ValueError)TypeError: issubclass() arg 2 must be a classissubclass(type(exc), ValueError)isinstanceexcisinstanceissubclassissubclass(MyCustomError, ValueError)exceptexceptisinstanceExceptionexcept Exception as e:if isinstance(e, ...)try:
risky_operation()
except ValueError as e:
handle_value_error(e)
except ConnectionError as e:
handle_network_error(e)
except Exception as e:
log_unexpected(e)
raise
exceptisinstanceissubclass(type(e), ...)type()isinstance(e, (ValueError, TypeError))if/elifisinstanceisinstanceclass ApiError(Exception):
pass
class ValidationError(ApiError):
pass
try:
raise ValidationError("field required")
except Exception as e:
print(isinstance(e, Exception)) # True
print(isinstance(e, ApiError)) # True
print(isinstance(e, ValidationError)) # True
e.__class__.__mro__isinstancee.__class__ is ValueErrorUnicodeDecodeErrorValueErrorisissubclassissubclass(e.__class__, ValueError)isinstanceissubclassissubclassif not issubclass(user_exc_class, BaseAppError): raise ConfigError(...)assert issubclass(TimeoutError, OSError)RetryableErrorissubclassissubclass(e, ValueError)isinstanceissubclass