Автор оригинала: 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
Вы отметите, что здесь есть несколько уровней вложенных функций. Обязательно изучите его, чтобы понять, что происходит. Наконец, нам нужно изменить наш сценарий тестирования:
Здесь мы импортируем наш декоратор и наш регистратор. Затем мы украсим нашу функцию и передаем декоратор нашего объекта регистратора. Если вы запускаете этот код, вы должны увидеть тот же файл, сгенерированный, как вы сделали в первом примере. Повеселись!