Почему я не могу выбрать трассировку ошибки в Python? - PullRequest
14 голосов
/ 26 мая 2011

С тех пор я нашел обходной путь, но все еще хочу знать ответ.

Ответы [ 2 ]

20 голосов
/ 26 мая 2011

В трассировке содержатся ссылки на стековые фреймы каждой функции / метода, которые были вызваны в текущем потоке, начиная с самого верхнего фрейма и заканчивая точкой возникновения ошибки. Каждый кадр стека также содержит ссылки на локальные и глобальные переменные, действовавшие на момент вызова каждой функции в стеке.

Поскольку для pickle нет способа узнать, что сериализовать и что игнорировать, если бы вы могли выбрать трассировку, вы бы в конечном итоге получили движущийся снимок всего состояния приложения: во время работы pickle другие потоки могут изменять значения общих переменных.

Одним из решений является создание объекта, который можно выбрать, для обхода трассировки и извлечения только той информации, которая вам нужна.

0 голосов
/ 14 декабря 2017

Полагаю, вы заинтересованы в сохранении полного контекста вызова ( traceback + globals + localals каждого кадра).

Thatбыло бы очень полезно определить разницу в поведении одной и той же функции в двух разных контекстах вызова или создать собственные расширенные инструменты для обработки, отображения или сравнения этих обратных трасс.

Проблема в том, что pickl не знает, как сериализовать все типы объектов, которые могут быть в locals или globals .

Полагаю, вы можете построить свой собственный объект и сохранить его, отфильтровывая все те объекты, которые не являются 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>"

, но вместо печати объектов вы можете добавить их в список с вашим собственным выбираемым представлением (a json или yml формат может быть лучше).

Возможно, вы хотите загрузить весь этот контекст вызова, чтобы воспроизвести ту же ситуацию для вашей функции без запуска сложного рабочего процесса, который ее генерирует.Я не знаю, можно ли это сделать (из-за ссылок на память), но в этом случае вам придется десериализовать его из своего формата.

...