我有一个函数我的原因异常,我希望它是一个装饰器。代码如下:
def des(i):
def new_func(func):
if i == 1:
raise Exception
else:
return func
return new_func
@des(1)
def func():
print "!!"
if __name__ == '__main__':
try:
func()
except Exception:
print 'error'
但输出是:
Traceback (most recent call last):
File "D:/des.py", line 10, in <module>
@des(1)
File "D:/des.py", line 4, in new_func
raise Exception
Exception
所以,我怎么能抓住这个例外?
答案 0 :(得分:2)
定义函数时会引发异常。捕获此异常的唯一方法是:
try:
@des(1)
def func():
print '!!'
except:
print 'error'
如果引起异常的原因令人困惑,请记住您的代码等同于:
def func():
print '!!'
func = des(1)(func)
# des(1) = new_func, so des(1)(func) is new_func(func)
答案 1 :(得分:1)
所以,现在你的代码基本归结为:
_des = des(1)
def _func();
print '!!'
func = _des(func)
您使用des
的返回值作为装饰器,我认为这会导致问题。
我想你可能想再次嵌套返回的函数:
def des(i): # container func.
def new_func(func):
def ret_func(*args, **kwargs):
if i == 1:
raise Exception
else:
return func(*args, **kwargs)
return ret_func # return the func with the bound variable
return new_func # return the func which creates the function w/ the bound var.
@des(1)
def func():
print "!!"
答案 2 :(得分:0)
我在这里缺少一个功能级别。
ITYM
import functools
def des(i): # this is the "decorator creator", called with des(1)
def deco(func): # this is returned and is the real decorator, called at function definition time
@functools.wraps(func) # sugar
def new_func(*a, **k): # and this is the function called on execution.
if i == 1:
raise Exception # I hope this is just for testing... better create a new exception for this
else:
return func(*a, **k)
return new_func
return deco
@des(1)
def func():
print "!!"
if __name__ == '__main__':
try:
func()
except Exception:
print 'error'
答案 3 :(得分:0)
正如其他答案所解释的那样,您当前的问题是,当装饰器应用于函数时,您将获得异常,而不是在调用函数时。
要解决此问题,您需要让装饰器返回一个执行异常提升的函数。这是如何工作的:
import functools
def des(i):
def decorator(func):
if i != 1:
return func # no wrapper needed
@functools.wraps(func)
def raiser(*args, **kwargs):
raise Exception
return raiser
return decorator
des
函数是“装饰工厂”。除了提供一个范围来保存它返回的装饰器的i
参数之外,它实际上没有做任何事情。
decorator
函数会检查是否需要执行任何特殊操作。如果不是,则返回未修改的修饰函数。如果i==1
,则返回自定义函数。
如果raiser
,i==1
函数是装饰者的返回值。它在调用时总是引发异常。应用functools.wraps
装饰器并非绝对必要,但它使其看起来更像原始函数(相同__name__
,__doc__
等)。