【问题标题】:How can I get a Python decorator to run after the decorated function has completed?在装饰函数完成后,如何让 Python 装饰器运行?
【发布时间】:2013-01-20 03:08:09
【问题描述】:

我想使用装饰器来处理各种功能的审核(主要是 Django 视图功能,但不限于此)。为了做到这一点,我希望能够审核函数 post-execution - 即函数正常运行,如果它无异常返回,那么装饰器会记录这一事实。

类似:

@audit_action(action='did something')
def do_something(*args, **kwargs):
    if args[0] == 'foo':
        return 'bar'
    else:
        return 'baz'

audit_action 只会在函数完成后运行。

【问题讨论】:

    标签: python decorator python-decorators


    【解决方案1】:

    装饰器通常返回一个包装函数;只需在调用包装函数后将您的逻辑放入包装函数中即可。

    def audit_action(action):
        def decorator_func(func):
            def wrapper_func(*args, **kwargs):
                # Invoke the wrapped function first
                retval = func(*args, **kwargs)
                # Now do something here with retval and/or action
                print('In wrapper_func, handling action {!r} after wrapped function returned {!r}'.format(action, retval))
                return retval
            return wrapper_func
        return decorator_func
    

    所以audit_action(action='did something') 是一个装饰器工厂,它返回一个作用域decorator_func,用于装饰你的do_something (do_something = decorator_func(do_something))。

    装饰后,您的do_something 引用已替换为wrapper_func。调用wrapper_func() 会导致调用原来的do_something(),然后你在包装函数中的代码就可以做事了。

    上面的代码,结合你的示例函数,给出以下输出:

    >>> do_something('foo')
    In wrapper_func, handling action 'did something' after wrapped function returned 'bar'
    'bar'
    

    【讨论】:

    • 你不知道我用了多少种不同的装饰器、包装器、函数和 retvals 组合来尝试让它工作。不仅感谢代码,还感谢解释。
    • 也许我遗漏了一些东西,但是你的装饰器在哪里被称为“do_something”?我期待一个@audit_action \n do_something('foo')
    • @ColinMac:我只摸了装饰器; do_something 定义来自问题,用固定装饰器装饰。重复该示例应用程序没有什么意义。
    • 对于正在学习的人(比如我),不清楚是否有其他事情发生。感谢您的澄清。
    【解决方案2】:

    你的装饰器可以在这里自己处理它,比如

    def audit_action(function_to_decorate):
        def wrapper(*args, **kw):
            # Calling your function
            output = function_to_decorate(*args, **kw)
            # Below this line you can do post processing
            print "In Post Processing...."
            return output
        return wrapper
    

    【讨论】:

    • OP 发布的示例使用了一个带有 action 参数的装饰器工厂。您需要另一层范围界定或类..
    猜你喜欢
    • 2017-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-25
    • 2016-07-25
    • 1970-01-01
    相关资源
    最近更新 更多