Why can't I pickle an error's Traceback in Python?

后端 未结 3 891
猫巷女王i
猫巷女王i 2021-02-18 16:36

I\'ve since found a work around, but still want to know the answer.

3条回答
  •  时光说笑
    2021-02-18 17:05

    I guess you are interested in saving the complete call context (traceback + globals + locals of each frame).

    That would be very useful to determine a difference of behavior of the same function in two different call contexts, or to build your own advanced tools to process, show or compare those tracebacks.

    The problem is that pickl doesn't know how to serialize all type of objects that could be in the locals or globals.

    I guess you can build your own object and save it, filtering out all those objects that are not picklabe. This code can serve as basis:

    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 ""
    

    but instead of printing the objects you can add them to a list with your own pickable representation ( a json or yml format might be better).

    Maybe you want to load all this call context in order to reproduce the same situation for your function without run the complicated workflow that generate it. I don't know if this can be done (because of memory references), but in that case you would need to de-serialize it from your format.

提交回复
热议问题