装饰器函数中的异常处理
exception handling in decorator function
Python 的新手,我有一堆函数可以在某些硬件上执行各种任务。每个函数都有不同数量的参数和 returns.
我想制作一种通用的 "retry" 包装器函数,它将捕获我的任何函数的异常并进行一些错误处理(例如重试任务)。
据我了解,我应该能够使用装饰器函数作为我的每个函数的通用包装器。这似乎可行,但我似乎无法真正从我的装饰器函数中调用的函数中获得任何异常。
我查看了各种示例并得出以下结论:
def retry(function):
def _retry(*args, **kwargs):
try:
reply = function(*args, **kwargs)
print "reply: ", reply
return reply
except PDError as msg:
print "_retry", msg
except:
print "_retry: another error"
return _retry
然后我使用我的一个函数的名称调用它:
value = retry(pd.command_get_parameter(0x00))
它似乎正确地调用了我的函数和 return,但是我的重试函数中从未捕获到异常。所以我无法处理错误并重试。
我也试过这个:
from functools import wraps
def retry(function):
@wraps(function)
def _retry(*args, **kwargs):
.....
我不确定我做错了什么,或者这是否是最好的方法。有人对如何执行此操作有建议吗?我真的不想为每个主要功能创建单独的 "retry" 功能。
正在将我的评论转换为答案:
你应该像这样使用:
def retry(function):
@wraps(function)
def _retry(*args, **kwargs):
try:
reply = function(*args, **kwargs)
print "reply: ", reply
return reply
except PDError as msg:
print "_retry", msg
except:
print "_retry: another error"
return _retry
class SomeClass(object):
@retry
def command_get_parameter(..):
return <some value>
s = SomeClass()
result = s.command_get_parameter(..) #retry(..) actually invokes this function.
装饰器接受一个函数,return一个装饰函数。修饰是能够在调用函数之前、之后执行某些操作或捕获异常等的东西。如果您使用上述语法 (@retry)
,解释器调用 retry(..)
,传入函数对象 (command_get_parameter
),并将该函数替换为由 retry(command_get_parameter)
编写的 return 函数。
发生的事情有点类似于以下步骤(伪代码):
new_command_get_parameter = retry(command_get_parameter) #@retry has this effect.
result = new_command_get_parameter(your_input)
不同之处在于,以上两个步骤是由解释器神奇地为您完成的——让代码更清晰、更易读。
目前您正在调用该函数,并将其结果传递给 retry(..)
,这显然是错误的。此外,它不会按照您希望的方式捕获异常。
Update:如果要重试访问实例变量,只需要让_retry
使用第一个参数作为self
.类似于:
def retry(func):
def _retry(self, *args, **kwargs):
print "Decorator printing a:", self.a
print "Decorator printing b:", self.b
try:
return func(*args, **kwargs)
except Exception as e:
print "Caught exception"
return "Grr.."
return _retry
class Temp(object):
def __init__(self, a, b):
self.a = a
self.b = b
@retry
def command(self, *args, **kwargs):
print "In command."
print "Args:", args
print "KWargs:", kwargs
raise Exception("DIE!")
t = Temp(3, 5)
print t.command(3,4,5, a=4, b=8)
输出:
Decorator printing a: 3
Decorator printing b: 5
In command.
Args: (4, 5)
KWargs: {'a': 4, 'b': 8}
Caught exception
Grr..
Python 的新手,我有一堆函数可以在某些硬件上执行各种任务。每个函数都有不同数量的参数和 returns.
我想制作一种通用的 "retry" 包装器函数,它将捕获我的任何函数的异常并进行一些错误处理(例如重试任务)。
据我了解,我应该能够使用装饰器函数作为我的每个函数的通用包装器。这似乎可行,但我似乎无法真正从我的装饰器函数中调用的函数中获得任何异常。
我查看了各种示例并得出以下结论:
def retry(function):
def _retry(*args, **kwargs):
try:
reply = function(*args, **kwargs)
print "reply: ", reply
return reply
except PDError as msg:
print "_retry", msg
except:
print "_retry: another error"
return _retry
然后我使用我的一个函数的名称调用它:
value = retry(pd.command_get_parameter(0x00))
它似乎正确地调用了我的函数和 return,但是我的重试函数中从未捕获到异常。所以我无法处理错误并重试。
我也试过这个:
from functools import wraps
def retry(function):
@wraps(function)
def _retry(*args, **kwargs):
.....
我不确定我做错了什么,或者这是否是最好的方法。有人对如何执行此操作有建议吗?我真的不想为每个主要功能创建单独的 "retry" 功能。
正在将我的评论转换为答案:
你应该像这样使用:
def retry(function):
@wraps(function)
def _retry(*args, **kwargs):
try:
reply = function(*args, **kwargs)
print "reply: ", reply
return reply
except PDError as msg:
print "_retry", msg
except:
print "_retry: another error"
return _retry
class SomeClass(object):
@retry
def command_get_parameter(..):
return <some value>
s = SomeClass()
result = s.command_get_parameter(..) #retry(..) actually invokes this function.
装饰器接受一个函数,return一个装饰函数。修饰是能够在调用函数之前、之后执行某些操作或捕获异常等的东西。如果您使用上述语法 (@retry)
,解释器调用 retry(..)
,传入函数对象 (command_get_parameter
),并将该函数替换为由 retry(command_get_parameter)
编写的 return 函数。
发生的事情有点类似于以下步骤(伪代码):
new_command_get_parameter = retry(command_get_parameter) #@retry has this effect.
result = new_command_get_parameter(your_input)
不同之处在于,以上两个步骤是由解释器神奇地为您完成的——让代码更清晰、更易读。
目前您正在调用该函数,并将其结果传递给 retry(..)
,这显然是错误的。此外,它不会按照您希望的方式捕获异常。
Update:如果要重试访问实例变量,只需要让_retry
使用第一个参数作为self
.类似于:
def retry(func):
def _retry(self, *args, **kwargs):
print "Decorator printing a:", self.a
print "Decorator printing b:", self.b
try:
return func(*args, **kwargs)
except Exception as e:
print "Caught exception"
return "Grr.."
return _retry
class Temp(object):
def __init__(self, a, b):
self.a = a
self.b = b
@retry
def command(self, *args, **kwargs):
print "In command."
print "Args:", args
print "KWargs:", kwargs
raise Exception("DIE!")
t = Temp(3, 5)
print t.command(3,4,5, a=4, b=8)
输出:
Decorator printing a: 3
Decorator printing b: 5
In command.
Args: (4, 5)
KWargs: {'a': 4, 'b': 8}
Caught exception
Grr..