在自定义Exception类内部获取stack trace时__traceback__为空如何解决
问题根本原因
Python 异常对象的__traceback__属性不是在实例化阶段赋值的:只有当解释器执行raise语句、将异常抛到调用栈的过程中,才会把当前的堆栈信息填充到异常对象的__traceback__属性中。你在自定义异常的__init__方法里直接调用发送邮件的逻辑,此时raise流程还没执行到填充__traceback__的步骤,因此拿到的只能是None。
可用解决方案
方案1:捕获异常后手动触发(兼容性最好,推荐)
不要在__init__里调用发邮件的方法,改为捕获异常后再调用,此时__traceback__已经完成填充:
import traceback class TaskFailure(Exception): def send_error_report(self): # 格式化完整堆栈信息 full_traceback = "".join(traceback.format_exception(type(self), self, self.__traceback__)) # 此处补充发送邮件的逻辑,full_traceback就是需要的堆栈内容 print(full_traceback) try: # 执行业务逻辑 raise TaskFailure("could not obtain template") except TaskFailure as e: e.send_error_report() # 如果需要继续向上抛出异常,加一行 raise 即可
方案2:全局钩子自动触发(无需手动捕获,适合未处理异常)
如果希望只要抛出该类异常就自动发邮件,不需要每次写try except手动调用,可以用sys.excepthook实现全局自动捕获:
import sys import traceback class TaskFailure(Exception): pass def custom_exception_handler(exc_type, exc_value, exc_traceback): # 仅处理自定义的TaskFailure异常 if issubclass(exc_type, TaskFailure): full_traceback = "".join(traceback.format_exception(exc_type, exc_value, exc_traceback)) # 发送邮件逻辑 print(full_traceback) # 保留系统默认的异常打印逻辑 sys.__excepthook__(exc_type, exc_value, exc_traceback) # 替换全局异常钩子 sys.excepthook = custom_exception_handler # 直接抛出异常即可自动触发邮件发送 raise TaskFailure("could not obtain template")
方案3:重写__raise__方法(Python 3.11+ 支持)
Python 3.11及以上版本支持异常类的__raise__魔术方法,该方法会在异常被raise、且__traceback__填充完成后触发,可以直接在类内部实现自动调用:
import traceback class TaskFailure(Exception): def __raise__(self, /): self.send_error_report() return super().__raise__() def send_error_report(self): full_traceback = "".join(traceback.format_exception(type(self), self, self.__traceback__)) print(full_traceback) raise TaskFailure("could not obtain template")
内容的提问来源于stack exchange,提问作者The Fool
相关产品推荐
相关产品推荐

