В собственных исключениях информацию о месте возникновения ошибки можно передавать, сохраняя данные из объекта 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 tracebackException (или его подклассов, например 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, чтобы не потерять информацию об исходном исключении.Рекомендации:
Используйте этот подход, когда важно предоставить детальную информацию о месте возникновения ошибки, особенно в сложных системах или библиотеках.