Как вывести traceback в except python

Как вывести traceback в except python

Пример использования:


import traceback
try:
1 / 0
except ZeroDivisionError:
traceback.print_exc()

В случае ошибки деления на ноль, данный код выведет следующее:


Traceback (most recent call last):
File "script.py", line 4, in <module>
1 / 0
ZeroDivisionError: division by zero

with open('error_log.txt', 'w') as f:
traceback.print_exc(file=f)

Помимо print_exc(), модуль предоставляет функцию format_exc(), которая возвращает traceback в виде строки. Это полезно, если необходимо передать информацию об ошибке в другие части программы или логировать её:


error_message = traceback.format_exc()
print(error_message)

Также можно получить traceback для конкретных исключений, используя метод format_exception(). Этот метод принимает три аргумента: тип исключения, само исключение и объект стека вызовов (обычно sys.exc_info()).


import sys
try:
1 / 0
except ZeroDivisionError:
exc_type, exc_value, exc_tb = sys.exc_info()
formatted_traceback = traceback.format_exception(exc_type, exc_value, exc_tb)
print(''.join(formatted_traceback))

Для корректной работы format_exc() должен вызываться строго внутри блока except, иначе он вернёт 'NoneType: None\n'. Это связано с тем, что функция использует текущее активное исключение, доступное только во время обработки ошибки.

Пример использования:

import traceback
try:
result = 10 / 0
except ZeroDivisionError:
error_details = traceback.format_exc()
with open('error.log', 'a') as log_file:
log_file.write(error_details)

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

format_exc() полезен при интеграции с внешними системами мониторинга – например, передаче ошибки в Sentry или отправке в телеграм-бота для уведомлений. Форматированный traceback легко сериализуется и передаётся как текст без необходимости обработки потока stderr.

Создайте логгер один раз в начале модуля:

import logging
logging.basicConfig(
level=logging.ERROR,
format="%(asctime)s [%(levelname)s] %(message)s",
handlers=[logging.StreamHandler()]
)
logger = logging.getLogger(__name__)

В блоке except используйте:

try:
# потенциально ошибочный код
except Exception as e:
logger.error("Произошло исключение", exc_info=True)

Параметр exc_info=True автоматически добавляет traceback в лог, включая тип исключения, сообщение и стек вызовов. Это предпочтительнее ручного форматирования, так как сохраняется структура и точность трассировки.

Для записи в файл добавьте FileHandler:

file_handler = logging.FileHandler("errors.log")
file_handler.setLevel(logging.ERROR)
file_handler.setFormatter(logging.Formatter("%(asctime)s [%(levelname)s] %(message)s"))
logger.addHandler(file_handler)

Если логгер используется в библиотеке, не вызывайте basicConfig(), а настраивайте только handlers. Это позволяет избежать конфликтов с конфигурацией основного приложения.

Логирование с exc_info гарантирует, что даже неожиданные исключения не останутся незамеченными при отладке и в продакшн-среде.

Для записи traceback в файл применяется модуль traceback в сочетании с функцией traceback.print_exc() или traceback.format_exc(). Это позволяет сохранить полную информацию об исключении для последующего анализа.

  • Откройте файл для записи в режиме 'a', чтобы сохранять все ошибки без перезаписи предыдущих.
  • Используйте traceback.print_exc(file=...) для немедленной записи в файл.
  • Если требуется предварительная обработка, применяйте traceback.format_exc() и записывайте результат вручную.

Пример с прямой записью:

import traceback
try:
1 / 0
except ZeroDivisionError:
with open("errors.log", "a") as f:
traceback.print_exc(file=f)

Пример с предварительным форматированием:

import traceback
try:
int("abc")
except ValueError:
error_text = traceback.format_exc()
with open("errors.log", "a") as f:
f.write(error_text)

Рекомендуется:

  • Указывать абсолютный путь к файлу лога, если скрипт запускается из разных директорий.
  • Использовать with для автоматического закрытия файлового дескриптора.
  • Очищать или архивировать лог периодически при постоянной работе программы.

Отображение информации о локальных переменных в traceback

Отображение информации о локальных переменных в traceback

Для анализа ошибок часто важно понимать не только стек вызовов, но и значения локальных переменных в момент исключения. В стандартном traceback такая информация отсутствует, но её можно получить, используя модуль traceback и объект sys.exc_info().

import sys
import traceback
def print_traceback_with_locals():
exc_type, exc_value, tb = sys.exc_info()
while tb is not None:
frame = tb.tb_frame
lineno = tb.tb_lineno
code = frame.f_code
filename = code.co_filename
funcname = code.co_name
print(f"\nФайл: {filename}, функция: {funcname}, строка: {lineno}")
for var, val in frame.f_locals.items():
try:
print(f"  {var} = {repr(val)}")
except Exception:
print(f"  {var} = <не удалось получить значение>")
tb = tb.tb_next

Для использования этой функции, достаточно вызвать её внутри блока except:

try:
# код с ошибкой
except:
print_traceback_with_locals()

Пример практического использования traceback для отладки

Пример практического использования traceback для отладки

Пример кода:

import traceback
from flask import Flask, request
app = Flask(__name__)
@app.route('/divide')
def divide():
try:
a = int(request.args.get('a'))
b = int(request.args.get('b'))
return str(a / b)
except Exception:
traceback.print_exc()
return "Ошибка обработки запроса", 500

В этом примере, если параметр b окажется равным нулю, в консоли будет выведён полный стек вызовов, включая строку, где произошло деление на ноль. Это позволяет быстро локализовать проблему без дополнительных логов.

Для сохранения traceback в файл используйте:

with open("error.log", "a") as f:
traceback.print_exc(file=f)

Вопрос-ответ:

Ссылка на основную публикацию