В собственных исключениях информацию о месте возникновения ошибки можно передавать, сохраняя данные из объекта traceback
. Это можно сделать, например, в конструкторе класса исключения.
Пример:
import traceback
class MyCustomError(Exception):
def __init__(self, message, traceback_info=None):
super().__init__(message)
self.traceback_info = traceback_info
try:
# Какой-то код, где может произойти ошибка
raise ValueError("Что-то пошло не так")
except ValueError as e:
tb = traceback.extract_stack() # or traceback.format_exc()
raise MyCustomError("Произошла ошибка!", traceback_info=tb) from e
В этом примере, информация о traceback сохраняется в атрибуте traceback_info
, и её можно получить при обработке исключения.
Для передачи информации о месте возникновения ошибки в пользовательских исключениях Python, можно использовать модуль traceback
. Он позволяет получить доступ к стеку вызовов и извлечь из него данные о файле, строке и имени функции, где произошло исключение.
Вот как это можно реализовать:
traceback
:import traceback
Exception
(или его подклассов, например ValueError
, TypeError
, если это логически соответствует ситуации):class MyCustomError(Exception):
def __init__(self, message, filename=None, line_number=None, function_name=None):
super().__init__(message)
self.filename = filename
self.line_number = line_number
self.function_name = function_name
def __str__(self):
location_info = ""
if self.filename and self.line_number and self.function_name:
location_info = f" (File: {self.filename}, Line: {self.line_number}, Function: {self.function_name})"
return f"{super().__str__()} {location_info}"
В конструктор класса MyCustomError
мы добавили параметры для хранения имени файла, номера строки и имени функции. Также переопределен метод __str__
, чтобы включить эту информацию в текстовое представление исключения.
traceback.extract_stack()
или traceback.format_exc()
чтобы получить информацию о стеке вызовов и создайте экземпляр вашего исключения:def my_function(x):
try:
if x < 0:
raise ValueError("Value must be non-negative")
result = 10 / x
return result
except ValueError as e:
# Get traceback information
trace = traceback.extract_stack()[-1] # Get info about the current frame
filename = trace.filename
line_number = trace.lineno
function_name = trace.name
raise MyCustomError(str(e), filename, line_number, function_name) from e # Preserve the original exception
def another_function():
try:
my_function(-5)
except MyCustomError as e:
print(f"Caught MyCustomError: {e}")
another_function()
В этом примере:
traceback.extract_stack()
возвращает список фреймов стека вызовов. Мы берем последний элемент [-1]
, чтобы получить информацию о текущем фрейме (где возникло исключение).MyCustomError
, передавая туда эту информацию.raise ... from e
: Это важно! Это позволяет связать новое исключение (MyCustomError
) с исходным исключением (ValueError
). Это сохраняет информацию о первопричине ошибки, что очень полезно для отладки.Альтернативный подход с traceback.format_exc()
:
Вместо traceback.extract_stack()
можно использовать traceback.format_exc()
, который возвращает форматированную строку с полной трассировкой стека. Однако, в этом случае вам придется парсить строку, чтобы извлечь нужную информацию, что менее удобно:
import traceback
class MyCustomError(Exception):
def __init__(self, message, traceback_info=None):
super().__init__(message)
self.traceback_info = traceback_info
def __str__(self):
traceback_str = ""
if self.traceback_info:
traceback_str = f"\nTraceback:\n{self.traceback_info}"
return f"{super().__str__()} {traceback_str}"
def my_function(x):
try:
if x < 0:
raise ValueError("Value must be non-negative")
result = 10 / x
return result
except ValueError as e:
traceback_info = traceback.format_exc()
raise MyCustomError(str(e), traceback_info) from e
def another_function():
try:
my_function(-5)
except MyCustomError as e:
print(f"Caught MyCustomError: {e}")
another_function()
В этом случае traceback_info
будет содержать полную трассировку стека в виде строки, которую можно будет распечатать или проанализировать.
Преимущества и недостатки:
raise ... from e
, чтобы не потерять информацию об исходном исключении.Рекомендации:
Используйте этот подход, когда важно предоставить детальную информацию о месте возникновения ошибки, особенно в сложных системах или библиотеках.