Пример использования:
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
и объект 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 для отладки
Пример кода:
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)