正如Mechmind回答的那样,堆栈跟踪仅由引发异常的位置与
try块的位置之间的帧组成。如果您需要完整的堆栈跟踪,显然您不走运。
除了可以将堆栈条目从顶层提取到当前帧之外,其他一切都可以进行
traceback.extract_stack管理。问题在于,通过所获取的信息
traceback.extract_stack来自直接检查堆栈帧而没有在任何时候创建回溯对象的情况,并且
loggingAPI需要一个回溯对象来影响回溯输出。
幸运的是,
logging不需要 实际的 追溯对象,它需要一个可以传递给
traceback模块格式化例程的对象。
traceback也不在乎-
它仅使用回溯的两个属性,即帧和行号。因此,应该有可能创建鸭子类型的人造回溯对象的链接列表,并将其作为回溯传递。
import sysclass FauxTb(object): def __init__(self, tb_frame, tb_lineno, tb_next): self.tb_frame = tb_frame self.tb_lineno = tb_lineno self.tb_next = tb_nextdef current_stack(skip=0): try: 1/0 except ZeroDivisionError: f = sys.exc_info()[2].tb_frame for i in xrange(skip + 2): f = f.f_back lst = [] while f is not None: lst.append((f, f.f_lineno)) f = f.f_back return lstdef extend_traceback(tb, stack): """Extend traceback with stack info.""" head = tb for tb_frame, tb_lineno in stack: head = FauxTb(tb_frame, tb_lineno, head) return headdef full_exc_info(): """Like sys.exc_info, but includes the full traceback.""" t, v, tb = sys.exc_info() full_tb = extend_traceback(tb, current_stack(1)) return t, v, full_tb
有了这些功能,您的代码仅需要进行小小的修改:
import loggingdef func(): try: raise Exception('Dummy') except: logging.error("Something awful happened!", exc_info=full_exc_info())def func2(): func()func2()
…给出预期的输出:
ERROR:root:Something awful happened!Traceback (most recent call last): File "a.py", line 52, in <module> func2() File "a.py", line 49, in func2 func() File "a.py", line 43, in func raise Exception('Dummy')Exception: Dummy
请注意,faux-traceback对象可用于自省(显示局部变量或作为自变量),
pdb.post_mortem()因为它们包含对实际堆栈框架的引用。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)