【问题标题】:What is the pythonic way to write my decorator?编写我的装饰器的 Pythonic 方式是什么?
【发布时间】:2019-07-26 10:09:19
【问题描述】:

我的目标是在我的程序遇到意外行为时引发 SystemExit 并记录错误。

我正在做类似的事情:

logger.error('Unexpected behaviour')
raise SystemExit

为了避免代码中的重复,我尝试编写一个装饰器以在每次 logger.error 调用时引发 SystemExit:

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)

所以我的问题是:我的装饰器是 Python 的吗?如果不是,最好的 Pythonic 方式是什么? (我看到人们使用@something,但我不明白它的用法)。

谢谢!

【问题讨论】:

  • 这看起来更像monkey patching
  • @bracco23 确实......所以它不是装饰器,因为它修改了函数的行为?
  • 它不是装饰器,因为您实际上是在用您编写的自定义函数更改logger 模块的error 函数,这实际上为原始函数添加了行为。这是一个棘手的举动,它的行为可能不像你想要的那样,特别是因为你让它抛出一个异常。我会选择外观模式,使用自定义对象,而该对象反过来使用记录器。
  • @bracco23 好的,你是对的,我将做一个单独的对象,而不是修改记录器。谢谢你的解释!

标签: python decorator python-decorators python-logging


【解决方案1】:

正如 cmets 中提到的,您所做的并不是装饰。这将是装饰:

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

我的装饰器是 Python 的吗?

可以说,这并不是因为补丁很难看,而且会增加意想不到的行为。更明确地说,您可以创建一个log_error_and_exit() 函数或使用logging.setLoggerClass(OurLogger) 注册您自己的日志记录类,并可能添加一个.fatal_error() 方法。但是,我认为您的解决方案是可以的。

【讨论】:

    猜你喜欢
    • 2016-06-20
    • 1970-01-01
    • 2021-09-28
    • 1970-01-01
    • 2019-12-13
    • 2016-11-25
    • 1970-01-01
    • 1970-01-01
    • 2010-09-21
    相关资源
    最近更新 更多