Python 如何捕获装饰器中的异常
我有一个函数我的原因例外,我希望它是一个装饰。代码如下:Python 如何捕获装饰器中的异常,python,python-decorators,Python,Python Decorators,我有一个函数我的原因例外,我希望它是一个装饰。代码如下: 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:
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
回溯(最近一次呼叫最后一次):
文件“D:/des.py”,第10行,在
@des(1)
文件“D:/des.py”,第4行,在新函数中
引发异常
例外情况
那么,如何捕获此异常呢?定义函数时会引发异常。捕获此异常的唯一方法是:
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)
现在,你的代码基本上可以归结为:
_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 "!!"
我这里缺少一个功能级别 伊蒂姆
正如其他答案所解释的,您当前的问题是,在将装饰程序应用于函数时,而不是在调用函数时,会引发异常 要解决这个问题,您需要使decorator返回一个执行异常引发的函数。以下是如何做到这一点:
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
,它将返回一个自定义函数
如果
i==1
,则raiser
函数是装饰器的返回值。它在被调用时总是引发异常。应用于它的functools.wrapps
装饰器并非绝对必要,但它使它看起来更像原始函数(相同的\uuuuuuu name\uuuuuuu
,\uuuu doc\uuuuuuu
,等等)。我相信这可能与您的问题有关:它工作,我理解它是如何工作的。谢谢:)但这会导致func出现未定义的函数是的,如果在定义函数的过程中出现异常,则不会定义该函数。除了在except
语句中为func
分配一个不同的函数之外,真的没有办法解决这个问题。如果我知道实际的代码是什么,而不是这个示例,我可以提供更多帮助。@LiGa是的,但您可以通过异常检测到这一点并进行适当的处理。我想您希望最内部的函数调用func
,而不仅仅是返回它。也就是说,将return func
替换为return func()
。您可能希望使用varargs语法(*args,**kwargs
)来允许修饰函数也接受一些参数。@Blckknght但是缺少一个级别的函数。看看我的答案。@glglgl:我不确定我是否明白。cwallenpool的答案有正确数量的嵌套函数,尽管没有您的答案那么简洁(并且没有()
使最里面的函数工作)。实际上,您可以在i==1
上设置创建最内层函数的条件,如果不需要,只需从装饰器(第二级函数)返回func
。@Blckknght是的,但是函数的装饰失败,而不是调用。@Blckknght d'oh!好了,现在修好了。这也是一个很好的解决方案:i==1
和之间的区别=
尽可能早地发生,但异常会在调用时发生,这是首选的。
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