Как в собственных исключениях передавать параметры, такие как имя функции или номер строки, где произошла ошибка?

Можно добавить параметры в конструктор класса исключения. Например:

 class MyCustomError(Exception):
  def __init__(self, message, function_name=None, line_number=None):
   super().__init__(message)
   self.function_name = function_name
   self.line_number = line_number

  def __str__(self):
   return f"{super().__str__()} (Function: {self.function_name}, Line: {self.line_number})"

 try:
  # Code that might raise an error
  raise MyCustomError("Something went wrong", function_name="my_function", line_number=42)
 except MyCustomError as e:
  print(e) # Output includes the message, function name, and line number
  

Для передачи параметров, таких как имя функции или номер строки, в собственные исключения в Python, можно использовать несколько подходов. Самый распространенный и рекомендуемый - это передавать их как аргументы конструктора класса исключения (__init__).

Пример реализации:


class MyCustomError(Exception):
    def __init__(self, message, function_name=None, line_number=None):
        super().__init__(message)  # Вызов конструктора базового класса Exception
        self.function_name = function_name
        self.line_number = line_number
        self.message = message  # Сохраняем сообщение об ошибке

    def __str__(self):
        error_message = self.message
        if self.function_name:
            error_message += f" in function: {self.function_name}"
        if self.line_number:
            error_message += f" at line: {self.line_number}"
        return error_message

Объяснение:

  • Мы определяем собственный класс исключения MyCustomError, наследуясь от базового класса Exception.
  • Конструктор __init__ принимает сообщение об ошибке (message), а также опциональные параметры function_name и line_number.
  • Внутри конструктора мы вызываем конструктор базового класса Exception с сообщением об ошибке (super().__init__(message)). Это важно для правильной работы механизма исключений.
  • Мы сохраняем переданные значения function_name и line_number в атрибуты объекта исключения.
  • Метод __str__ переопределен, чтобы предоставить удобное строковое представление исключения, включая информацию о функции и номере строки, если они доступны.

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


import inspect
import traceback

def my_function(x):
    try:
        if x < 0:
            frame = inspect.currentframe()
            raise MyCustomError("Value cannot be negative",
                                function_name=my_function.__name__,
                                line_number=frame.f_lineno)
        return x * 2
    except MyCustomError as e:
        print(e)
        # Дополнительная обработка исключения, например, логирование
        traceback.print_exc()

my_function(-5) # Вызовет MyCustomError
my_function(5)

Дополнительные замечания:

  • Функция inspect.currentframe() позволяет получить информацию о текущем фрейме стека вызовов, включая номер строки.
  • Использование traceback.print_exc() полезно для отладки, так как выводит полную трассировку стека, показывая путь выполнения программы до момента возникновения исключения.
  • Метод __name__ у функции возвращает ее имя в виде строки.
  • Вместо inspect.currentframe().f_lineno можно также использовать sys._getframe().f_lineno. Однако, sys._getframe() считается деталью реализации CPython и не рекомендуется к использованию в production коде, так как его поведение может измениться в будущих версиях. inspect - более надежный вариант.
  • Старайтесь делать сообщения об ошибках максимально информативными, чтобы облегчить отладку.

Этот подход позволяет не только передавать произвольные параметры в исключение, но и предоставляет гибкий способ форматирования сообщения об ошибке и извлечения полезной информации для отладки.

0