logging
для записи информации об исключении, включая трассировку стека, в файл или другой источник данных. Это позволяет отслеживать возникновение и контекст ошибки.traceback.format_exc()
позволяет получить отформатированную строку трассировки.Для регистрации ошибок, вызванных собственными исключениями в Python, используется несколько техник, позволяющих отслеживать, анализировать и исправлять проблемы в коде. Вот основные из них:
logging
:
logging
- это стандартный модуль Python для гибкой и мощной регистрации событий, включая ошибки. При возникновении собственного исключения можно записать информацию об ошибке в лог с использованием разных уровней (DEBUG, INFO, WARNING, ERROR, CRITICAL) в зависимости от серьезности.
import logging
logging.basicConfig(level=logging.ERROR,
filename='my_app.log',
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
class MyCustomError(Exception):
pass
def my_function(value):
try:
if value < 0:
raise MyCustomError("Value must be non-negative")
# ... остальной код
except MyCustomError as e:
logging.error(f"An error occurred: {e}", exc_info=True) # exc_info=True включает трассировку стека
# Дополнительная обработка ошибки (например, отправка уведомления)
# raise # Переброс исключения, если это необходимо для дальнейшей обработки
Ключевые моменты:
logging
позволяет определить куда будут записываться логи (файл, консоль, сетевой ресурс), какой уровень сообщений будет регистрироваться, и формат сообщения.exc_info=True
включает в лог трассировку стека, что критически важно для отладки.raise
) после логирования, если необходимо, чтобы ошибка обрабатывалась на более высоком уровне.Когда происходит исключение, Python автоматически генерирует трассировку стека, которая показывает последовательность вызовов функций, приведших к исключению. Модули traceback
и sys
позволяют получать и обрабатывать эту информацию.
import traceback
import sys
class MyCustomError(Exception):
pass
def my_function(value):
try:
if value < 0:
raise MyCustomError("Value must be non-negative")
# ... остальной код
except MyCustomError as e:
print("Exception occurred:")
traceback.print_exc() # Печатает трассировку стека в стандартный поток ошибок
# Или можно получить трассировку в виде строки:
# exc_type, exc_value, exc_traceback = sys.exc_info()
# traceback_details = traceback.format_exception(exc_type, exc_value, exc_traceback)
# for line in traceback_details:
# print(line, end="")
Трассировку можно отправить в лог-файл или использовать для создания детального сообщения об ошибке.
Для больших и сложных приложений рекомендуется использовать внешние системы мониторинга, такие как Sentry, Rollbar, ELK stack (Elasticsearch, Logstash, Kibana), Prometheus + Grafana, которые позволяют централизованно собирать, анализировать и визуализировать логи и ошибки.
# Пример интеграции с Sentry (псевдокод):
# import sentry_sdk
# from sentry_sdk import capture_exception
# sentry_sdk.init(dsn="YOUR_SENTRY_DSN")
# class MyCustomError(Exception):
# pass
# def my_function(value):
# try:
# if value < 0:
# raise MyCustomError("Value must be non-negative")
# # ... остальной код
# except MyCustomError as e:
# capture_exception(e) # Отправляет исключение в Sentry
# raise
Эти системы предоставляют мощные инструменты для фильтрации, поиска, группировки ошибок и уведомлений о новых или повторяющихся проблемах.
Помимо стандартной трассировки стека, важно включать в логи дополнительную контекстную информацию, которая поможет понять, что происходило в системе в момент возникновения ошибки. Это может быть:
import logging
class MyCustomError(Exception):
def __init__(self, message, user_id=None, transaction_id=None):
super().__init__(message)
self.user_id = user_id
self.transaction_id = transaction_id
def my_function(value, user_id, transaction_id):
try:
if value < 0:
raise MyCustomError("Value must be non-negative", user_id=user_id, transaction_id=transaction_id)
# ... остальной код
except MyCustomError as e:
logging.error(f"Error: {e}, User ID: {e.user_id}, Transaction ID: {e.transaction_id}", exc_info=True)
raise
Передача контекстной информации в исключение и ее последующее логирование значительно упрощает отладку и анализ причин возникновения ошибок.
Правильное форматирование логов делает их более читабельными и удобными для анализа. Важно включать в лог-сообщения дату и время, уровень сообщения, имя модуля и функции, вызвавшей ошибку, и саму ошибку.
logging.basicConfig(level=logging.ERROR,
format='%(asctime)s - %(levelname)s - %(module)s.%(funcName)s:%(lineno)d - %(message)s')
Выбор конкретной техники зависит от масштаба и сложности приложения, а также от требований к отладке и мониторингу. Часто используется комбинация нескольких подходов для обеспечения наиболее полной и эффективной регистрации ошибок.