自定义异常捕获后SendError分支下代码未执行原因排查
SendError异常分支不触发的核心原因
出现抛出SendError却直接进入MMM异常处理逻辑的问题,本质是Python异常捕获的匹配规则命中了以下几种情况:
- 最常见原因:
except块顺序写反+异常继承关系不符合预期
Python的异常捕获是从上到下顺序匹配的,只要抛出的异常是当前except声明类型的实例(包括该类的所有子类实例),就会直接进入该分支,后续所有except块都会被跳过。如果你的SendError自定义类继承自MMM,同时你把except MMM的代码块写在了except SendError的前面,就会直接触发这个问题:SendError作为MMM的子类,会被提前写好的MMM捕获逻辑接住,后面的SendError分支永远没有执行机会。
错误示例:class MMM(Exception): pass class SendError(MMM): pass # SendError是MMM的子类 try: # 第272行代码 raise SendError("触发发送错误") except MMM: # 写在最前面,直接接住所有MMM及其子类的异常 # 第353行逻辑 会被直接执行 pass except SendError: # 永远走不到,异常已经被上面的分支接住了 # 第281行逻辑 无法触发 pass - 第二种可能:类引用不一致
如果raise语句用的SendError和except语句引用的SendError不是同一个类对象,会导致匹配失败。常见场景包括:不同模块下存在同名的SendError类、循环导入导致异常类引用失效、导入异常时写错了导入路径,实际拿到的是其他类。 - 第三种可能:抛出的异常不符合预期
比如手误在raise时写了raise MMM,或者实例化SendError的过程中(比如__init__方法里的逻辑)隐式抛出了MMM异常,导致实际进入捕获流程的异常对象本身就是MMM类型。
快速排查方法
- 在raise语句的位置打断点,打印抛出的异常对象的类型和继承链:执行
print(type(e), type(e).__mro__),确认异常的实际类型、是否是MMM的子类。 - 检查所有except块的排列顺序,把越具体的子类异常的捕获放在越靠前的位置,父类异常的捕获统一放在所有子类捕获的最后。
- 分别在raise位置和except位置打印
id(SendError),如果两个id不一致,就说明存在类引用错误,修正导入路径即可。
内容的提问来源于stack exchange,提问作者Mateusz Adamek
相关产品推荐
相关产品推荐

