如何 "decorate" 调用站点中的函数而不是定义

How to "decorate" a function in the call site rather than definition

我在处理异常的有用内省助手,因此想概括代码而不是一直复制粘贴它。我有

def state_on_exc(f):
    @wraps(f)
    def wrapper(*args, **kwargs):
        try:
            result = f(*args, **kwargs)
            return result
        except Exception as e:
            ex_type, exc_value, tb = sys.exc_info()
            if tb is not None:
                prev = tb
                curr = tb.tb_next
                while curr is not None:
                    prev = curr
                    curr = curr.tb_next
                print(prev.tb_frame.f_locals)
            raise e

@state_on_exc
def apply(f):
    return f

def myfunc():
    a = 5
    raise ValueError

apply(myfunc())

但是包装器似乎没有在异常时调用(它专门在 myfunc() 中引发)- 它不打印任何局部变量。有没有什么合适的方法可以达到同样的效果,或者有更好的方法吗?

非常接近。

  1. 您需要 return 装饰器中的包装函数。
  2. 要重新引发,您不应将异常对象添加到引发 stmt。
  3. 要装饰函数,将函数对象传递给装饰器函数。
  4. 调用修饰函数,调用修饰函数。而不是非修饰函数。

示例:

from functools import wraps

def decorate(f):
    @wraps(f)
    def wrapper(*args, **kwargs):
        try:
            return f(*args, **kwargs)
        except Exception as e:
            # handle exception
            print("handled exception:", type(e))
            # re-raise
            raise
    return wrapper

def myfunc():
    a = 5
    raise ValueError

decorated_fun = decorate(myfunc)
decorated_fun()

输出为:

$ python3 test.py
handled exception: <class 'ValueError'>
Traceback (most recent call last):
  File "tt.py", line 25, in <module>
    decorated_fun()
  File "tt.py", line 7, in wrapper
    result = f(*args, **kwargs)
  File "tt.py", line 22, in myfunc
    raise ValueError
ValueError