2013-02-05 66 views
25

我想用一个装饰器来处理各种函数的审计(主要是Django视图函数,但不是唯一的)。为了做到这一点,我希望能够审计功能执行后 - 即该函数正常运行,如果它没有例外返回,则装饰器记录事实。如何在装饰函数完成后让Python装饰器运行?

喜欢的东西:

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

当函数完成后audit_action将只运行。

回答

26

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

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_somethingdo_something = decorator_func(do_something))。

装修后,您的do_something参考文献已被wrapper_func替代。调用wrapper_func()会导致原来的do_something()被调用,然后你的代码在包装器func可以做的事情。

上面的代码,再加上你的榜样作用,给出了以下的输出:

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

你不知道有多少个不同的组合装饰,包装,功能和retvals我用尽了这个工作。不仅感谢代码,而且感谢您的解释。 –

3

你的装饰可以在这里自己来处理它,就像

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 wrapper 
+0

OP发布的示例使用了一个用'action'参数调用的装饰器工厂。你需要另一层范围或类别.. –

+0

根据OP的例子更新了答案:) – avasal