Рубрики
Без рубрики

Python: как создать декоратор регистрации исключений

Получите практические, реальные навыки Python на наших ресурсах и пути

Автор оригинала: Mike Driscoll.

На днях я решил, что хочу создать декоратор, чтобы ловить исключения и входить в систему. Я нашел довольно сложный пример на Github Что я использовал для некоторых идей о том, как приблизиться к этой задаче и придумал следующее:

# exception_decor.py

import functools
import logging

def create_logger():
    """
    Creates a logging object and returns it
    """
    logger = logging.getLogger("example_logger")
    logger.setLevel(logging.INFO)

    # create the logging file handler
    fh = logging.FileHandler("/path/to/test.log")

    fmt = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    formatter = logging.Formatter(fmt)
    fh.setFormatter(formatter)

    # add handler to logger object
    logger.addHandler(fh)
    return logger


def exception(function):
    """
    A decorator that wraps the passed in function and logs 
    exceptions should one occur
    """
    @functools.wraps(function)
    def wrapper(*args, **kwargs):
        logger = create_logger()
        try:
            return function(*args, **kwargs)
        except:
            # log the exception
            err = "There was an exception in  "
            err += function.__name__
            logger.exception(err)

            # re-raise the exception
            raise
    return wrapper

В этом коде у нас есть две функции. Первый создает объект ведения журнала и возвращает его. Вторая функция – наша функция декоратора. Здесь мы обертываем пропущенные функции в попытке/кроме и регистрируйте любые исключения, которые происходят с использованием нашего регистратора. Вы отметите, что я также регистрирую имя функции, которое произошло исключение.

Теперь нам просто нужно проверить этот декоратор. Для этого вы можете создать новый сценарий Python и добавить к нему следующий код. Убедитесь, что вы сохраняете это в том же месте, которое вы сохранили код выше.

from exception_decor import exception

@exception
def zero_divide():
    1 / 0

if __name__ == '__main__':
    zero_divide()

Когда вы запускаете этот код из командной строки, вы должны заканчивать файл журнала, который имеет следующее содержимое:

2016-06-09 08:26:50,874 - example_logger - ERROR - There was an exception in  zero_divide
Traceback (most recent call last):
  File "/home/mike/exception_decor.py", line 29, in wrapper
    return function(*args, **kwargs)
  File "/home/mike/test_exceptions.py", line 5, in zero_divide
    1 / 0
ZeroDivisionError: integer division or modulo by zero

Я думал, что это был удобный кусок кода, и я надеюсь, что вы найдете это полезным тоже!

Обновить : Устойчивый читатель указывал, что было бы хорошей идеей обобщить этот скрипт такой, что вы можете передавать декоратор объекта регистратора. Итак, давайте посмотрим, как это работает!

Передача регистратора в наш декоратор

Во-первых, давайте разделим наш журнал код в свой собственный модуль. Давайте назовем это Exception_logger.py Отказ Вот код для ввода этого файла:

Далее нам нужно изменить наш код декоратора, чтобы мы могли принять регистратор в качестве аргумента. Обязательно сохраните его как Exception_decor.py

Вы отметите, что здесь есть несколько уровней вложенных функций. Обязательно изучите его, чтобы понять, что происходит. Наконец, нам нужно изменить наш сценарий тестирования:

Здесь мы импортируем наш декоратор и наш регистратор. Затем мы украсим нашу функцию и передаем декоратор нашего объекта регистратора. Если вы запускаете этот код, вы должны увидеть тот же файл, сгенерированный, как вы сделали в первом примере. Повеселись!