小编典典

获取完整的追溯

python

我怎样才能在以下情况下完全追踪,包括呼叫func2func功能?

import traceback

def func():
    try:
        raise Exception('Dummy')
    except:
        traceback.print_exc()

def func2():
    func()


func2()

当我运行它时,我得到:

Traceback (most recent call last):
  File "test.py", line 5, in func
    raise Exception('Dummy')
Exception: Dummy

traceback.format_stack()不是我想要的,因为需要将traceback对象传递给第三方模块。

我对这种情况特别感兴趣:

import logging


def func():
    try:
        raise Exception('Dummy')
    except:
        logging.exception("Something awful happened!")


def func2():
    func()


func2()

在这种情况下,我得到:

ERROR:root:Something awful happened!
Traceback (most recent call last):
  File "test.py", line 9, in func
    raise Exception('Dummy')
Exception: Dummy

阅读 124

收藏
2020-12-20

共1个答案

小编典典

正如Mechmind回答的那样,堆栈跟踪仅由引发异常的位置与try块的位置之间的帧组成。如果您需要完整的堆栈跟踪,显然您不走运。

除了可以将堆栈条目从顶层提取到当前帧之外,其他一切都可以进行traceback.extract_stack管理。问题在于,通过所获取的信息traceback.extract_stack来自直接检查堆栈帧而没有在任何时候创建回溯对象的情况,并且loggingAPI需要一个回溯对象来影响回溯输出。

幸运的是,logging不需要 实际的 追溯对象,它需要一个可以传递给traceback模块格式化例程的对象。traceback也不在乎-
它仅使用回溯的两个属性,即帧和行号。因此,应该有可能创建鸭子类型的人造回溯对象的链接列表,并将其作为回溯传递。

import sys

class 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_next

def 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 lst

def 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 head

def 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 logging

def 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()因为它们包含对实际堆栈框架的引用。

2020-12-20