[英]How to catch an exception in a decorator
我有一個函數,我的原因異常,我希望它成為裝飾器。 代碼如下:
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
因此,如何捕獲此異常?
定義函數時會引發異常。 捕獲此異常的唯一方法是:
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 "!!"
我在這里缺少一個功能級別。
企業
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'
正如其他答案所解釋的那樣,當前的問題是,在將裝飾器應用於函數時(而不是在調用函數時)引發了異常。
要解決此問題,您需要使裝飾器返回一個進行異常引發的函數。 這是可能的工作方式:
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.wraps
適用於它的裝飾是不是絕對必要的,但它使得它看起來更像原來的功能(同__name__
, __doc__
等)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.