使用functools.wraps decorator尝试类的每个函数



我正试图定义一个装饰器以便执行一个类方法,先尝试一下,如果检测到错误,请将其提出来,说明失败的方法,以便用户可以看到错误是在哪个方法中。

在这里,我展示了我的代码的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((缺少1个必需的位置参数:"name">

或误解了具有自函数的自类。

作为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的尝试中,调用func的结果从未返回,您需要在*args之外还包括**kwargs,以便使用命名参数。即A().animals(num=1)仅在处理kwargs时有效。

对于带参数的装饰器,您需要多一个嵌套级别:

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'

我会这样做,希望它能有所帮助。

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],您还可以获得回溯消息,并指向发生异常的行。

值得注意的是,在编写装饰器时,它应该适用于您在应用程序中使用的其他函数。

相关内容

  • 没有找到相关文章

最新更新