Моя цель — поднять SystemExit и зарегистрировать ошибку, когда моя программа сталкивается с неожиданным поведением.
Я делал что-то вроде:
logger.error('Unexpected behaviour')
raise SystemExit
Чтобы избежать повторения в моем коде, я попытался написать декоратор, который поднимал бы SystemExit при каждом вызове logger.error:
error = logger.error
def error_from_logger(msg) :
''' Decorator for logger.error to kill the program at the call '''
error(msg)
raise SystemExit
logger.error = error_from_logger
del(error_from_logger)
Итак, мой вопрос: является ли мой декоратор pythonic? И если нет, то как лучше всего это написать на pythonic? (Я видел, как люди используют @something, но я не понимаю, как это используется).
Спасибо!
@bracco23 bracco23 Действительно ... Значит, это не декоратор, потому что он изменяет поведение функции?
Это не декоратор, потому что вы на самом деле меняете функцию error
модуля logger
на собственную, написанную вами, которая фактически добавляет поведение к исходной. Это сложный ход, он может вести себя не так, как вы хотите, тем более что он выдает исключение. Я бы выбрал шаблон Facade, используя пользовательский объект, который, в свою очередь, использует вместо этого регистратор.
@ bracco23 Хорошо, вы правы, я сделаю отдельный объект вместо того, чтобы изменять объект регистратора. Спасибо за объяснение!
Как уже упоминалось в комментариях, то, что вы сделали, не совсем украшает. Это будет украшение:
def call_then_exit(func):
def called_and_exited(*args, **kwargs):
func(*args, **kwargs)
raise SystemExit
return called_and_exited
logger = logging.getLogger()
logger.error = call_then_exit(logger.error) # this is the decoration
logger.error("some error has happened") # prints the message and exists
@decorator — это просто синтаксический сахар, который вы используете при объявлении функции. Это не очень полезно для вас, если вы используете функцию/метод, объявленную в другом месте.
@call_then_exit # this is the decoration
def say_hi():
print('hello')
say_hi() # prints 'hi' and exits
print('did we exit?') # we never reach this
Is my decorator pythonic?
Возможно, это не потому, что исправление уродливо и добавляет неожиданное поведение. Чтобы быть более явным, вы можете создать функцию log_error_and_exit()
или зарегистрировать свой собственный класс ведения журнала с помощью logging.setLoggerClass(OurLogger)
и, возможно, добавить метод .fatal_error()
. Тем не менее, я думаю, что ваше решение в порядке как есть.
Это больше похоже на исправление обезьяны