Автор оригинала: Doug Hellmann.
Цель:
Извлечение, форматирование и печать исключений и трассировок стека.
Модуль traceback
работает со стеком вызовов для создания сообщений об ошибках. traceback – это трассировка стека от точки обработчика исключения вниз по цепочке вызовов до точки, где было вызвано исключение. К трассировке также можно получить доступ из текущего стека вызовов вверх от точки вызова (и без контекста ошибки), что полезно для определения путей, по которым идет функция.
API высокого уровня в traceback
использует экземпляры StackSummary
и FrameSummary
для хранения представления стека. Эти классы могут быть созданы из трассировки или текущего стека выполнения, а затем обработаны аналогичным образом.
Функции низкого уровня в traceback
делятся на несколько общих категорий. Существуют функции для извлечения необработанных трассировок из текущей среды выполнения (либо обработчик исключений для трассировки, либо обычный стек). Извлеченная трассировка стека – это последовательность кортежей, содержащих имя файла, номер строки, имя функции и текст исходной строки.
После извлечения трассировку стека можно отформатировать с помощью таких функций, как format_exception ()
, format_stack ()
и т. Д. Функции форматирования возвращают список строк с сообщениями, отформатированными для печати . Также существуют сокращенные функции для печати форматированных значений.
Хотя функции в traceback
по умолчанию имитируют поведение интерактивного интерпретатора, они также полезны для обработки исключений в ситуациях, когда выгрузка полной трассировки стека на консоль нежелательна. Например, веб-приложению может потребоваться отформатировать трассировку, чтобы она хорошо выглядела в HTML, а IDE может преобразовать элементы трассировки стека в интерактивный список, который позволяет пользователю просматривать источник.
Вспомогательные функции
Примеры в этом разделе используют модуль traceback_example.py
.
traceback_example.py
import traceback import sys def produce_exception(recursion_level2): sys.stdout.flush() if recursion_level: produce_exception(recursion_level - 1) else: raise RuntimeError() def call_function(f, recursion_level2): if recursion_level: return call_function(f, recursion_level - 1) else: return f()
Изучение стека
Чтобы проверить текущий стек, создайте StackSummary
из walk_stack ()
.
traceback_stacksummary.py
import traceback import sys from traceback_example import call_function def f(): summary traceback.StackSummary.extract( traceback.walk_stack(None) ) print(''.join(summary.format())) print('Calling f() directly:') f() print() print('Calling f() from 3 levels deep:') call_function(f)
Метод format ()
создает последовательность форматированных строк, готовых к печати.
$ python3 traceback_stacksummary.py Calling f() directly: File "traceback_stacksummary.py", line 18, in f traceback.walk_stack(None) File "traceback_stacksummary.py", line 24, inf() Calling f() from 3 levels deep: File "traceback_stacksummary.py", line 18, in f traceback.walk_stack(None) File ".../traceback_example.py", line 26, in call_function return f() File ".../traceback_example.py", line 24, in call_function return call_function(f, recursion_level - 1) File ".../traceback_example.py", line 24, in call_function return call_function(f, recursion_level - 1) File "traceback_stacksummary.py", line 28, in call_function(f)
StackSummary
– это повторяемый контейнер, содержащий экземпляры FrameSummary
.
traceback_framesummary.py
import traceback import sys from traceback_example import call_function template ( '{fs.filename:<26}:{fs.lineno}:{fs.name}:\n' ' {fs.line}' ) def f(): summary traceback.StackSummary.extract( traceback.walk_stack(None) ) for fs in summary: print(template.format(fsfs)) print('Calling f() directly:') f() print() print('Calling f() from 3 levels deep:') call_function(f)
Каждый FrameSummary
описывает кадр стека, включая информацию о том, где в исходных файлах программы находится контекст выполнения.
$ python3 traceback_framesummary.py Calling f() directly: traceback_framesummary.py :23:f: traceback.walk_stack(None) traceback_framesummary.py :30:: f() Calling f() from 3 levels deep: traceback_framesummary.py :23:f: traceback.walk_stack(None) .../traceback_example.py:26:call_function: return f() .../traceback_example.py:24:call_function: return call_function(f, recursion_level - 1) .../traceback_example.py:24:call_function: return call_function(f, recursion_level - 1) traceback_framesummary.py :34: : call_function(f)
TracebackException
Класс TracebackException
– это высокоуровневый интерфейс для создания StackSummary
при обработке обратной трассировки.
traceback_tracebackexception.py
import traceback import sys from traceback_example import produce_exception print('with no exception:') exc_type, exc_value, exc_tb sys.exc_info() tbe traceback.TracebackException(exc_type, exc_value, exc_tb) print(''.join(tbe.format())) print('\nwith exception:') try: produce_exception() except Exception as err: exc_type, exc_value, exc_tb sys.exc_info() tbe traceback.TracebackException( exc_type, exc_value, exc_tb, ) print(''.join(tbe.format())) print('\nexception only:') print(''.join(tbe.format_exception_only()))
Метод format ()
создает отформатированную версию полной трассировки, а format_exception_only ()
показывает только сообщение об исключении.
$ python3 traceback_tracebackexception.py with no exception: None: None with exception: Traceback (most recent call last): File "traceback_tracebackexception.py", line 22, inproduce_exception() File ".../traceback_example.py", line 17, in produce_exception produce_exception(recursion_level - 1) File ".../traceback_example.py", line 17, in produce_exception produce_exception(recursion_level - 1) File ".../traceback_example.py", line 19, in produce_exception raise RuntimeError() RuntimeError exception only: RuntimeError
API-интерфейсы исключений низкого уровня
Другой способ обработки отчетов об исключениях – использование print_exc ()
. Он использует sys.exc_info ()
для получения информации об исключении для текущего потока, форматирует результаты и печатает текст в дескриптор файла ( sys.stderr
по умолчанию ).
traceback_print_exc.py
import traceback import sys from traceback_example import produce_exception print('print_exc() with no exception:') traceback.print_exc(filesys.stdout) print() try: produce_exception() except Exception as err: print('print_exc():') traceback.print_exc(filesys.stdout) print() print('print_exc(1):') traceback.print_exc(limit1, filesys.stdout)
В этом примере дескриптор файла для sys.stdout
заменяется так, чтобы информационные сообщения и сообщения трассировки были правильно смешаны:
$ python3 traceback_print_exc.py print_exc() with no exception: NoneType: None print_exc(): Traceback (most recent call last): File "traceback_print_exc.py", line 20, inproduce_exception() File ".../traceback_example.py", line 17, in produce_exception produce_exception(recursion_level - 1) File ".../traceback_example.py", line 17, in produce_exception produce_exception(recursion_level - 1) File ".../traceback_example.py", line 19, in produce_exception raise RuntimeError() RuntimeError print_exc(1): Traceback (most recent call last): File "traceback_print_exc.py", line 20, in produce_exception() RuntimeError
print_exc ()
– это просто ярлык для print_exception ()
, который требует явных аргументов.
traceback_print_exception.py
import traceback import sys from traceback_example import produce_exception try: produce_exception() except Exception as err: print('print_exception():') exc_type, exc_value, exc_tb sys.exc_info() traceback.print_exception(exc_type, exc_value, exc_tb)
Аргументы для print_exception ()
создаются sys.exc_info ()
.
$ python3 traceback_print_exception.py Traceback (most recent call last): File "traceback_print_exception.py", line 16, inproduce_exception() File ".../traceback_example.py", line 17, in produce_exception produce_exception(recursion_level - 1) File ".../traceback_example.py", line 17, in produce_exception produce_exception(recursion_level - 1) File ".../traceback_example.py", line 19, in produce_exception raise RuntimeError() RuntimeError print_exception():
print_exception ()
использует format_exception ()
для подготовки текста.
traceback_format_exception.py
import traceback import sys from pprint import pprint from traceback_example import produce_exception try: produce_exception() except Exception as err: print('format_exception():') exc_type, exc_value, exc_tb sys.exc_info() pprint( traceback.format_exception(exc_type, exc_value, exc_tb), width65, )
Те же три аргумента, тип исключения, значение исключения и трассировка, используются с format_exception ()
.
$ python3 traceback_format_exception.py format_exception(): ['Traceback (most recent call last):\n', ' File "traceback_format_exception.py", line 17, in\n' ' produce_exception()\n', ' File ' '".../traceback_example.py", ' 'line 17, in produce_exception\n' ' produce_exception(recursion_level - 1)\n', ' File ' '".../traceback_example.py", ' 'line 17, in produce_exception\n' ' produce_exception(recursion_level - 1)\n', ' File ' '".../traceback_example.py", ' 'line 19, in produce_exception\n' ' raise RuntimeError()\n', 'RuntimeError\n']
Чтобы обработать трассировку другим способом, например, отформатировать ее по-другому, используйте extract_tb ()
, чтобы получить данные в удобной для использования форме.
traceback_extract_tb.py
import traceback import sys import os from traceback_example import produce_exception template '{filename:<23}:{linenum}:{funcname}:\n {source}' try: produce_exception() except Exception as err: print('format_exception():') exc_type, exc_value, exc_tb sys.exc_info() for tb_info in traceback.extract_tb(exc_tb): filename, linenum, funcname, source tb_info if funcname '': funcname funcname + '()' print(template.format( filenameos.path.basename(filename), linenumlinenum, sourcesource, funcnamefuncname) )
Возвращаемое значение – это список записей с каждого уровня стека, представленного трассировкой. Каждая запись представляет собой кортеж из четырех частей: имя исходного файла, номер строки в этом файле, имя функции и исходный текст из этой строки с удаленным пробелом (если источник доступен).
$ python3 traceback_extract_tb.py format_exception(): traceback_extract_tb.py:18:: produce_exception() traceback_example.py :17:produce_exception(): produce_exception(recursion_level - 1) traceback_example.py :17:produce_exception(): produce_exception(recursion_level - 1) traceback_example.py :19:produce_exception(): raise RuntimeError()
API-интерфейсы стека низкого уровня
Есть аналогичный набор функций для выполнения тех же операций с текущим стеком вызовов вместо трассировки. print_stack ()
печатает текущий стек без создания исключения.
traceback_print_stack.py
import traceback import sys from traceback_example import call_function def f(): traceback.print_stack(filesys.stdout) print('Calling f() directly:') f() print() print('Calling f() from 3 levels deep:') call_function(f)
Результат выглядит как трассировка без сообщения об ошибке.
$ python3 traceback_print_stack.py Calling f() directly: File "traceback_print_stack.py", line 21, inf() File "traceback_print_stack.py", line 17, in f Calling f() from 3 levels deep: File "traceback_print_stack.py", line 25, in call_function(f) File ".../traceback_example.py", line 24, in call_function return call_function(f, recursion_level - 1) File ".../traceback_example.py", line 24, in call_function return call_function(f, recursion_level - 1) File ".../traceback_example.py", line 26, in call_function return f() File "traceback_print_stack.py", line 17, in f
format_stack ()
подготавливает трассировку стека так же, как format_exception ()
готовит трассировку.
traceback_format_stack.py
import traceback import sys from pprint import pprint from traceback_example import call_function def f(): return traceback.format_stack() formatted_stack call_function(f) pprint(formatted_stack)
Он возвращает список строк, каждая из которых составляет одну строку вывода.
$ python3 traceback_format_stack.py [' File "traceback_format_stack.py", line 21, in\n' ' formatted_stack = call_function(f)\n', ' File ' '".../traceback_example.py", ' 'line 24, in call_function\n' ' return call_function(f, recursion_level - 1)\n', ' File ' '".../traceback_example.py", ' 'line 24, in call_function\n' ' return call_function(f, recursion_level - 1)\n', ' File ' '".../traceback_example.py", ' 'line 26, in call_function\n' ' return f()\n', ' File "traceback_format_stack.py", line 18, in f\n' ' return traceback.format_stack()\n']
Функция extract_stack ()
работает так же, как extract_tb ()
.
traceback_extract_stack.py
import traceback import sys import os from traceback_example import call_function template '{filename:<26}:{linenum}:{funcname}:\n {source}' def f(): return traceback.extract_stack() stack call_function(f) for filename, linenum, funcname, source in stack: if funcname '': funcname funcname + '()' print(template.format( filenameos.path.basename(filename), linenumlinenum, sourcesource, funcnamefuncname) )
Он также принимает аргументы, не показанные здесь, чтобы начать с альтернативного места в кадре стека или ограничить глубину обхода.
$ python3 traceback_extract_stack.py traceback_extract_stack.py:23:: stack = call_function(f) traceback_example.py :24:call_function(): return call_function(f, recursion_level - 1) traceback_example.py :24:call_function(): return call_function(f, recursion_level - 1) traceback_example.py :26:call_function(): return f() traceback_extract_stack.py:20:f(): return traceback.extract_stack()
Смотрите также
- стандартная библиотечная документация для отслеживания
- sys – модуль
sys
включает синглтоны, содержащие текущее исключение. - inspect – модуль
inspect
включает другие функции для проверки кадров в стеке. - cgitb – еще один модуль для красивого форматирования трассировок.