Как сделать декоратор для логирования exception`ов?

Декоратор - это функция, которая принимает другую функцию в качестве аргумента и возвращает новую функцию, обычно с расширенным или измененным поведением. В случае с декоратором для логирования exception'ов, мы хотим создать декоратор, который будет автоматически логировать исключения, возникающие внутри декорируемой функции.

В Python для логирования исключений мы можем использовать стандартный модуль logging, который предоставляет мощный функционал для логирования данных. Предположим, что у нас уже есть настроенный логгер logger из модуля logging, и мы хотим использовать его для логирования исключений.

Декоратор для логирования exception'ов можно реализовать следующим образом:

import logging
import functools

def exception_logger(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except Exception as e:
            logger.error(f"Exception in {func.__name__}: {e}")
            # Обработка исключения
            # Можно выбросить исключение дальше, если требуется, используя `raise`

    return wrapper

Давайте рассмотрим этот код подробнее:

1. Мы импортируем модули logging и functools, а также нашу заранее настроенный логгер logger.
2. Создаем функцию exception_logger, которая принимает функцию func в качестве аргумента.
3. Мы используем декоратор functools.wraps для сохранения метаданных исходной функции func, что полезно для отладки.
4. Внутри декоратора определяется внутренняя функция wrapper, которая будет вызвана вместо исходной функции func.
5. Внутри этой функции wrapper обрабатываем исключения, которые могут возникнуть при вызове func.
6. Если исключение возникает, мы записываем сообщение о нем в лог с помощью logger.error, используя имя функции func.__name__ и информацию об исключении e.
7. Здесь вы также можете добавить любую другую обработку исключений, если это необходимо. Например, вы можете выбросить исключение дальше с помощью raise, если требуется.
8. В конце мы возвращаем обернутую функцию wrapper, которая теперь будет вызвана вместо исходной функции func.

Теперь мы можем использовать этот декоратор для логирования exception'ов в любой функции, которую мы хотим обернуть. Просто поместите @exception_logger над определением функции, как показано ниже:

@exception_logger
def my_function():
    # Код функции

Когда функция my_function будет вызвана, и если внутри нее возникнет исключение, оно будет автоматически залогировано. Вы можете выбрать уровень логирования (например, debug, info, error) в зависимости от ваших потребностей.