21

从那以后,我找到了解决方法,但仍然想知道答案。

4

3 回答 3

23

回溯保存对在当前线程上调用的每个函数/方法的堆栈帧的引用,从最顶层帧一直到引发错误的点。每个堆栈帧还保存对调用堆栈中的每个函数时有效的局部和全局变量的引用。

由于 pickle 无法知道要序列化什么以及忽略什么,因此如果您能够 pickle 回溯,您最终会腌制整个应用程序状态的移动快照:当 pickle 运行时,其他线程可能正在修改共享变量的值。

一种解决方案是创建一个可腌制对象来回溯并仅提取您需要保存的信息。

于 2011-05-26T00:44:16.023 回答
2

您可以使用tblib

    try:
        1 / 0
    except Exception as e:
         raise Exception("foo") from e
except Exception as e:
    s = pickle.dumps(e)
raise pickle.loads(s)
于 2020-09-25T06:25:41.273 回答
1

我猜您有兴趣保存完整的调用上下文(每帧的回溯+全局变量+局部变量)。

这对于确定同一函数在两个不同调用上下文中的行为差异,或者构建您自己的高级工具来处理、显示或比较这些回溯非常有用。

问题是pickl不知道如何序列化可能在localsglobals中的所有类型的对象。

我想您可以构建自己的对象并保存它,过滤掉所有那些不是picklabe的对象。此代码可以作为基础:

import sys, traceback

def print_exc_plus():
    """
    Print the usual traceback information, followed by a listing of all the
    local variables in each frame.
    """
    tb = sys.exc_info()[2]
    while 1:
        if not tb.tb_next:
            break
        tb = tb.tb_next
    stack = []
    f = tb.tb_frame
    while f:
        stack.append(f)
        f = f.f_back
    stack.reverse()
    traceback.print_exc()
    print "Locals by frame, innermost last"
    for frame in stack:
        print
        print "Frame %s in %s at line %s" % (frame.f_code.co_name,
                                             frame.f_code.co_filename,
                                             frame.f_lineno)
        for key, value in frame.f_locals.items():
            print "\t%20s = " % key,
            #We have to be careful not to cause a new error in our error
            #printer! Calling str() on an unknown object could cause an
            #error we don't want.
            try:                   
                print value
            except:
                print "<ERROR WHILE PRINTING VALUE>"

但不是打印对象,您可以将它们添加到您自己的可选择表示形式的列表中(jsonyml格式可能更好)。

也许您想加载所有这些调用上下文,以便为您的函数重现相同的情况,而无需运行生成它的复杂工作流程。我不知道这是否可以做到(因为内存引用),但在这种情况下,你需要从你的格式中反序列化它。

于 2017-12-14T12:48:29.000 回答