Как получить полную трассировку стека исключений в Python - PullRequest
29 голосов
/ 22 мая 2011

Следующий фрагмент:

import traceback

def a():
    b()

def b():
    try:
        c()
    except:
        traceback.print_exc()

def c():
    assert False

a()

Создает этот вывод:

Traceback (most recent call last):
  File "test.py", line 8, in b
    c()
  File "test.py", line 13, in c
    assert False
AssertionError

Что я должен использовать, если я хочу полную трассировку стека, включая вызов?

Если это имеет значение, у меня есть Python 2.6.6

edit: То, что я хотел бы получить, - это та же информация, что и я, если бы я оставил попытку, за исключением случая, когда исключение распространялось на верхний уровень.,Этот фрагмент кода, например:

def a():
    b()

def b():
    c()

def c():
    assert False

a()

Создает этот вывод:

Traceback (most recent call last):
  File "test.py", line 10, in <module>
    a()
  File "test.py", line 2, in a
    b()
  File "test.py", line 5, in b
    c()
  File "test.py", line 8, in c
    assert False
AssertionError

Ответы [ 4 ]

21 голосов
/ 16 мая 2013

Вот функция, основанная на этом ответе .Он также будет работать, когда нет никаких исключений:

def full_stack():
    import traceback, sys
    exc = sys.exc_info()[0]
    stack = traceback.extract_stack()[:-1]  # last one would be full_stack()
    if exc is not None:  # i.e. an exception is present
        del stack[-1]       # remove call of full_stack, the printed exception
                            # will contain the caught exception caller instead
    trc = 'Traceback (most recent call last):\n'
    stackstr = trc + ''.join(traceback.format_list(stack))
    if exc is not None:
         stackstr += '  ' + traceback.format_exc().lstrip(trc)
    return stackstr

print full_stack() напечатает полную трассировку стека до самого верха, включая, например, вызовы IPython interactiveshell.py, поскольку (насколько мне известно) нетспособ узнать, кто будет ловить исключения.Вероятно, в любом случае не стоит выяснять ...

Если print full_stack() вызывается из блока except, full_stack будет включать трассировку стека до raise.В стандартном интерпретаторе Python это будет идентично сообщению, которое вы получаете, когда не перехватываете исключение (вот почему этот del stack[-1] присутствует, вам важен не блок except, а блок try).

20 голосов
/ 22 сентября 2012

Я не знаю, есть ли лучший способ, но вот что я сделал:

import traceback
import sys

def format_exception(e):
    exception_list = traceback.format_stack()
    exception_list = exception_list[:-2]
    exception_list.extend(traceback.format_tb(sys.exc_info()[2]))
    exception_list.extend(traceback.format_exception_only(sys.exc_info()[0], sys.exc_info()[1]))

    exception_str = "Traceback (most recent call last):\n"
    exception_str += "".join(exception_list)
    # Removing the last \n
    exception_str = exception_str[:-1]

    return exception_str

def main1():
    main2()

def main2():
    try:
        main3()
    except Exception as e:
        print "Printing only the traceback above the current stack frame"
        print "".join(traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))
        print
        print "Printing the full traceback as if we had not caught it here..."
        print format_exception(e)

def main3():
    raise Exception()

if __name__ == '__main__':
    main1()

И вот результат, который я получаю:

Printing only the traceback above the current stack frame
Traceback (most recent call last):
  File "exc.py", line 22, in main2
    main3()
  File "exc.py", line 31, in main3
    raise Exception()
Exception


Printing the full traceback as if we had not caught it here...
Traceback (most recent call last):
  File "exc.py", line 34, in <module>
    main1()
  File "exc.py", line 18, in main1
    main2()
  File "exc.py", line 22, in main2
    main3()
  File "exc.py", line 31, in main3
    raise Exception()
Exception
7 голосов
/ 22 мая 2011

Использование

 traceback.print_stack()

http://docs.python.org/library/traceback.html#traceback.print_stack

suxmac2 $ python out.py 
  File "out.py", line 16, in <module>
    a()
  File "out.py", line 5, in a
    b()
  File "out.py", line 11, in b
    traceback.print_stack()
2 голосов
/ 12 ноября 2017


Вот чуть лучший вариант ответа Тобиаса Кинцлера . Он работает так же, но может вызываться не прямо в блоке except, а где-то глубже. Другими словами, этот вариант будет печатать те же стеки, когда вызывается как

try:
   ...
except Exception:
    print full_stack()

или

def print_full_stack():
    print full_stack()

try:
   ...
except Exception:
    print_full_stack()

Вот код:

def full_stack():
    import traceback, sys
    exc = sys.exc_info()[0]
    if exc is not None:
        f = sys.exc_info()[-1].tb_frame.f_back
        stack = traceback.extract_stack(f)
    else:
        stack = traceback.extract_stack()[:-1]  # last one would be full_stack()
    trc = 'Traceback (most recent call last):\n'
    stackstr = trc + ''.join(traceback.format_list(stack))
    if exc is not None:
        stackstr += '  ' + traceback.format_exc().lstrip(trc)
    return stackstr
...