import logging
logging.basicConfig(level=logging.ERROR)
class MyCustomError(Exception):
    pass
try:
    # Код, который может вызвать исключение
    raise MyCustomError("Произошла ошибка!")
except MyCustomError as e:
    logging.exception(e) # или logging.error("Ошибка!", exc_info=True)
  Для того, чтобы собственное исключение передавалось в лог, нужно сделать несколько вещей:
class MyCustomException(Exception):
    def __init__(self, message, details=None):
        super().__init__(message)
        self.details = details
    def __str__(self): # Переопределяем __str__ для более информативного логирования
        base_message = super().__str__()
        if self.details:
            return f"{base_message} (Details: {self.details})"
        return base_message
      
import logging
# Настройка логгера
logger = logging.getLogger(__name__)
logger.setLevel(logging.ERROR) # Устанавливаем минимальный уровень логирования
# Создаем обработчик для записи в файл (или в консоль, или куда угодно)
file_handler = logging.FileHandler('my_app.log')
file_handler.setLevel(logging.ERROR)
# Создаем форматтер для логов (определяет формат записи)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
# Добавляем обработчик к логгеру
logger.addHandler(file_handler)
# Пример с записью в консоль:
# console_handler = logging.StreamHandler()
# console_handler.setLevel(logging.ERROR) # можно задать другой уровень для консоли
# console_handler.setFormatter(formatter)
# logger.addHandler(console_handler)
      
def my_function(value):
    try:
        if value < 0:
            raise MyCustomException("Value must be non-negative", details={"value": value})
        result = 10 / value # Можем спровоцировать ZeroDivisionError
        return result
    except MyCustomException as e:
        logger.exception("Caught MyCustomException:") # Записывает исключение с трассировкой
        # Дополнительная обработка исключения (например, graceful shutdown)
    except ZeroDivisionError as e:
         logger.exception("Caught ZeroDivisionError:")
         # Альтернатива: logger.error(f"ZeroDivisionError: {e}", exc_info=True) # exc_info=True тоже добавляет трассировку
    except Exception as e: # Ловим все остальные исключения.  Важно, чтобы это был последний except
        logger.exception("An unexpected error occurred:") # Логируем любое другое исключение
    finally:
        #  Код, который всегда выполняется (например, освобождение ресурсов)
        pass
# Пример использования
my_function(-5)
my_function(0)
my_function(5)