我有一个属性,它有一个断言来检查值是否为 str 类型。
为了捕获这个 assertionError,我根据我在网上找到的例子创建了一个装饰器。
装饰器:
def catch_assertionerror(function):
def handle_problems(*args, **kwargs):
try:
return function(*args, **kwargs)
except AssertionError:
# log_error(err.args[0])
print "error caught"
return handle_problems
属性:
@catch_assertionerror
@name.setter
def name(self, value):
assert isinstance(value, str), "This value should be a string"
self._name = name
设置名称属性:
self.name = self.parse_name_from_xml()
当我运行这段代码时,没有显示任何错误,所以我猜它被捕获了,但另一方面,错误消息并没有打印到屏幕上。
然后我尝试了一个我在 Stachoverflow 上找到的更简单的例子:
def handleError(function):
def handleProblems():
try:
function()
except Exception:
print "Oh noes"
return handleProblems
@handleError
def example():
raise Exception("Boom!")
这也处理了错误,但没有将错误消息打印到屏幕上。
有人可以向我解释一下我在这里缺少什么吗?
请您参考如下方法:
你的后一个例子对我有用,但你的主要问题在于你没有用 catch_assertionerror 包装一个函数
@catch_assertionerror
@name.setter
def name(self, value):
assert isinstance(value, str), "This value should be a string"
self._name = name
但是一个descriptor .更糟糕的是,您返回的是一个函数,而不是包装原始函数的新描述符。现在,当您分配给 name 属性时,您只需将包装函数替换为分配的值即可。
逐步使用您的原始类定义:
class X(object):
@property
def name(self):
return self._name
@catch_assertionerror
@name.setter
def name(self, value):
assert isinstance(value, str), "This value should be a string"
self._name = value
>>> x = X()
>>> x.name
<unbound method X.handle_problems>
>>> x.__dict__
{}
>>> x.name = 2
>>> x.name
2
>>> x.__dict__
{'name': 2}
您必须做的是包装方法函数,然后将其传递给描述符处理装饰器:
class X(object):
@property
def name(self):
return self._name
@name.setter
@catch_assertionerror
def name(self, value):
assert isinstance(value, str), "This value should be a string"
self._name = value
等等:
>>> x = X()
>>> x.name
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in name
AttributeError: 'X' object has no attribute '_name'
>>> x.name = 2
error caught
>>> x.name = "asdf"
>>> x.name
'asdf'
将来考虑使用 functools.wraps 和 functools.update_wrapper。没有它们,您的类和函数将更难检查,因为您的包装器将隐藏原始的:
>>> @catch_assertionerror
... def this_name_should_show(): pass
...
>>> this_name_should_show
<function handle_problems at 0x7fd3d69e22a8>
以这种方式定义装饰器:
def catch_assertionerror(function):
@wraps(function)
def handle_problems(*args, **kwargs):
...
return handle_problems
将保留原始函数的信息:
>>> @catch_assertionerror
... def this_name_should_show(): pass
...
>>> this_name_should_show
<function this_name_should_show at 0x7fd3d69e21b8>
在您的情况下,它还会向您表明存在问题:
# When trying to define the class
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in X
File "<stdin>", line 2, in catch_assertionerror
File "/usr/lib/python2.7/functools.py", line 33, in update_wrapper
setattr(wrapper, attr, getattr(wrapped, attr))
AttributeError: 'property' object has no attribute '__module__'
