[英]How to catch an exception in a decorator
I have a function my cause exception and i want it to be a decorator. 我有一个函数,我的原因异常,我希望它成为装饰器。 The code is as follow:
代码如下:
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'
but the output is: 但输出是:
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
so, how can I catch this exception? 因此,如何捕获此异常?
The exception is raised when you define the function. 定义函数时会引发异常。 The only way to catch this exception would be:
捕获此异常的唯一方法是:
try:
@des(1)
def func():
print '!!'
except:
print 'error'
If it's confusing why this is causing an exception, remember your code is equivalent to: 如果这引起异常的原因令人困惑,请记住您的代码等效于:
def func():
print '!!'
func = des(1)(func)
# des(1) = new_func, so des(1)(func) is new_func(func)
So, right now your code basically boils down to this: 因此,现在您的代码基本上可以归结为:
_des = des(1)
def _func();
print '!!'
func = _des(func)
You're using the return value of des
as the decorator, and I think that is causing the problem. 您使用
des
的返回值作为装饰器,我认为这是造成问题的原因。
I think you might want to nest that returned function one more time: 我想您可能想再嵌套一次返回的函数:
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 "!!"
I am missing one function level here. 我在这里缺少一个功能级别。
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'
As the other answers have explained, your current issue is that you're getting the exception raised when the decorator is applied to the function, not when the function is called. 正如其他答案所解释的那样,当前的问题是,在将装饰器应用于函数时(而不是在调用函数时)引发了异常。
To fix this, you need to make the decorator return a function that does the exception raising. 要解决此问题,您需要使装饰器返回一个进行异常引发的函数。 Here's how that could work:
这是可能的工作方式:
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
The des
function is a "decorator factory". des
功能是一个“装饰工厂”。 It doesn't really doesn't do anything other than providing a scope to hold the i
parameter for the decorator that it returns. 除了提供一个范围来保存返回的装饰器的
i
参数外,它实际上并没有做任何其他事情。
The decorator
function does the check to see if anything special needs to be done. decorator
功能进行检查,看是否需要做一些特殊的事情。 If not, it returns the decorated function unmodified. 如果不是,则返回修饰后的函数,不做修改。 If
i==1
, it returns a custom function. 如果
i==1
,则返回自定义函数。
The raiser
function is the decorator's return value if i==1
. 如果
i==1
则raiser
函数是装饰器的返回值。 It always raises an exception when it is called. 总是在调用时引发异常。 The
functools.wraps
decorator applied to it is not strictly necessary, but it makes it look more like the original function (same __name__
, __doc__
, etc). 该
functools.wraps
适用于它的装饰是不是绝对必要的,但它使得它看起来更像原来的功能(同__name__
, __doc__
等)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.