使用 functools.wraps 装饰器尝试 class 的每个函数
Try each function of a class with functools.wraps decorator
我正在尝试定义一个 装饰器 以执行 class 方法,先尝试一下 并且,如果检测到错误,则提出它并提及失败的方法,以便用户可以看到错误是在哪个方法中。
这里我展示了我的代码的 MRE(最小的、可重现的示例)。
from functools import wraps
def trier(func):
"""Decorator for trying A-class methods"""
@wraps(func)
def inner_func(self, name, *args):
try:
func(self, *args)
except:
print(f"An error apeared while {name}")
return inner_func
class A:
def __init__(self):
self._animals = 2
self._humans = 5
@trier('getting animals')
def animals(self, num):
return self._animals + num
@trier('getting humans')
def humans(self):
return self._humans
A().animals
许多错误正在引发,例如:
TypeError: inner_func() missing 1 required positional argument: 'name'
或误会自我class与自我功能
对于带参数的装饰器,还需要多一层嵌套:
from functools import wraps
def trier(name):
def wrapper(func):
@wraps(func)
def inner(*args, **kwargs):
try:
return func(*args, **kwargs)
except:
print(f"An error apeared while executing {name!r}")
return inner
return wrapper
class A:
def __init__(self):
self._animals = 2
self._humans = 5
@trier('getting animals')
def animals(self, num):
return self._animals + num
@trier('getting humans')
def humans(self):
return self._hoomans # wrong attribute name
a = A()
a.humans() # An error apeared while executing 'getting humans'
作为 Stefan 答案的替代方案,下面简单地使用 @trier
不带任何参数来修饰函数,然后在打印出错误消息时我们可以用 func.__name__
获得名称。
from functools import wraps
def trier(func):
"""Decorator for trying A-class methods"""
@wraps(func)
def inner_func(self, *args, **kwargs):
try:
return func(self, *args, **kwargs)
except:
print(f"An error apeared in {func.__name__}")
return inner_func
class A:
def __init__(self):
self._animals = 2
self._humans = 5
@trier
def animals(self, num):
return self._animals + num
@trier
def humans(self):
return self._humans
print(A().animals(1))
我还修复了代码中的几个错误:在 trier
的 try 中,except 调用 func
的结果从未返回,您需要包含 **kwargs
除了 *args
之外,您还可以使用命名参数。 IE。 A().animals(num=1)
仅在处理 kwargs
.
时有效
我会这样做,希望对您有所帮助。
from functools import wraps
import sys
def trier(func):
"""Decorator for trying A-class methods"""
@wraps(func)
def inner_func(self, *args, **kwargs):
print(f'Calling {func.__name__}')
try:
func(self, *args, **kwargs)
except:
print(f"An error apeared on function : {func.__name__}")
e = sys.exc_info()[2]
raise Exception(f"Exception occured on line: {e.tb_next.tb_lineno}")
return inner_func
class A:
def __init__(self):
self._animals = 2
self._humans = 5
@trier
def get_animals(self, num):
return self._animals + num
@trier
def get_humans(self):
return self._humans
@trier
def function_raising_exception(self):
raise Exception('This is some exception')
if __name__ == "__main__":
a = A()
a.get_animals(2)
a.function_raising_exception()
使用e = sys.exc_info()[2]
,同样可以得到回溯信息,指向异常发生的行
值得注意的是,在编写装饰器时,它应该适用于您将在应用中使用的其他功能。
我正在尝试定义一个 装饰器 以执行 class 方法,先尝试一下 并且,如果检测到错误,则提出它并提及失败的方法,以便用户可以看到错误是在哪个方法中。
这里我展示了我的代码的 MRE(最小的、可重现的示例)。
from functools import wraps
def trier(func):
"""Decorator for trying A-class methods"""
@wraps(func)
def inner_func(self, name, *args):
try:
func(self, *args)
except:
print(f"An error apeared while {name}")
return inner_func
class A:
def __init__(self):
self._animals = 2
self._humans = 5
@trier('getting animals')
def animals(self, num):
return self._animals + num
@trier('getting humans')
def humans(self):
return self._humans
A().animals
许多错误正在引发,例如:
TypeError: inner_func() missing 1 required positional argument: 'name'
或误会自我class与自我功能
对于带参数的装饰器,还需要多一层嵌套:
from functools import wraps
def trier(name):
def wrapper(func):
@wraps(func)
def inner(*args, **kwargs):
try:
return func(*args, **kwargs)
except:
print(f"An error apeared while executing {name!r}")
return inner
return wrapper
class A:
def __init__(self):
self._animals = 2
self._humans = 5
@trier('getting animals')
def animals(self, num):
return self._animals + num
@trier('getting humans')
def humans(self):
return self._hoomans # wrong attribute name
a = A()
a.humans() # An error apeared while executing 'getting humans'
作为 Stefan 答案的替代方案,下面简单地使用 @trier
不带任何参数来修饰函数,然后在打印出错误消息时我们可以用 func.__name__
获得名称。
from functools import wraps
def trier(func):
"""Decorator for trying A-class methods"""
@wraps(func)
def inner_func(self, *args, **kwargs):
try:
return func(self, *args, **kwargs)
except:
print(f"An error apeared in {func.__name__}")
return inner_func
class A:
def __init__(self):
self._animals = 2
self._humans = 5
@trier
def animals(self, num):
return self._animals + num
@trier
def humans(self):
return self._humans
print(A().animals(1))
我还修复了代码中的几个错误:在 trier
的 try 中,except 调用 func
的结果从未返回,您需要包含 **kwargs
除了 *args
之外,您还可以使用命名参数。 IE。 A().animals(num=1)
仅在处理 kwargs
.
我会这样做,希望对您有所帮助。
from functools import wraps
import sys
def trier(func):
"""Decorator for trying A-class methods"""
@wraps(func)
def inner_func(self, *args, **kwargs):
print(f'Calling {func.__name__}')
try:
func(self, *args, **kwargs)
except:
print(f"An error apeared on function : {func.__name__}")
e = sys.exc_info()[2]
raise Exception(f"Exception occured on line: {e.tb_next.tb_lineno}")
return inner_func
class A:
def __init__(self):
self._animals = 2
self._humans = 5
@trier
def get_animals(self, num):
return self._animals + num
@trier
def get_humans(self):
return self._humans
@trier
def function_raising_exception(self):
raise Exception('This is some exception')
if __name__ == "__main__":
a = A()
a.get_animals(2)
a.function_raising_exception()
使用e = sys.exc_info()[2]
,同样可以得到回溯信息,指向异常发生的行
值得注意的是,在编写装饰器时,它应该适用于您将在应用中使用的其他功能。