是否可以编写异常处理程序来捕获类中所有方法生成的运行时错误?我可以通过try / except包围每个人来完成它:
class MyError(Exception):
def __init__(self, obj, method):
print 'Debug info:', repr(obj.data), method.__name__
raise
class MyClass:
def __init__(self, data):
self.data = data
def f1(self):
try:
all method code here, maybe failing at run time
except:
raise MyError(self, self.f1)
我想知道是否有更通用的方法来实现相同的目标 - 因为在课堂的任何地方都会出现任何错误。我希望能够访问类数据以打印一些调试信息。 另外,如何获取失败的方法名称(示例中为f1)?
更新:感谢所有人提供的明确答案,装饰者的想法看起来就像是要走的路。
关于捕获所有异常的风险:raise
分支中的except
语句应该重新引发异常而不会丢失任何信息,不是吗?这就是我把它放在MyError中的原因......
答案 0 :(得分:17)
警告:如果你想要这样的东西,很可能你不会......但如果你真的想...
类似的东西:
import functools
def catch_exception(f):
@functools.wraps(f)
def func(*args, **kwargs):
try:
return f(*args, **kwargs)
except Exception as e:
print 'Caught an exception in', f.__name__
return func
class Test(object):
def __init__(self, val):
self.val = val
@catch_exception
def calc():
return self.val / 0
t = Test(3)
t.calc()
显示了如何装饰各个功能。然后,您可以创建一个类装饰器,将此装饰器应用于每个方法(注意classmethod's
/ staticmethod's
/ properties
等...)
答案 1 :(得分:13)
假设你有@Jon Clement答案的装饰catch_exception
......
class ErrorCatcher(type):
def __new__(cls, name, bases, dct):
for m in dct:
if hasattr(dct[m], '__call__'):
dct[m] = catch_exception(dct[m])
return type.__new__(cls, name, bases, dct)
class Test(object):
__metaclass__ = ErrorCatcher
def __init__(self, val):
self.val = val
def calc(self):
return self.val / 0
元类将catch_exception
应用于定义Test
时看似方法的所有内容。
在回复有关每种方法的自定义消息的评论时,可以附加这样的消息(甚至是回调函数来生成消息)作为属性:
class Test(object):
__metaclass__ = ErrorCatcher
def __init__(self, val):
self.val = val
def calc(self):
return self.val / 0
calc.msg = "Dividing by 0 is ill-advised"
catch_exception
装饰器会在其参数上查找msg
属性,并在处理异常时使用它(如果找到)。
这种方法可以延长;而不是字符串,msg
可以是异常类型到字符串的映射。在任何一种情况下,都可以使用任意回调函数替换字符串(当然,支持来自catch_exception
),例如,将引发的异常作为参数。
def calc_handler(exc):
# ...
calc.callback = calc_handler
答案 2 :(得分:3)
装饰者在这里是一个很好的解决方案。
以下是您如何做到这一点的示例:
import inspect
def catch_exception_decorator(function):
def decorated_function:
try:
function()
except:
raise MyError(self.__class__, inspect.stack()[1][3])
return decorated_function
class MyClass(object):
def __init__(self):
...
@catch_exception_decorator
def f1(self):
...
@catch_exception_decorator在函数顶部是f1 = catch_exception_decorator(f1)
的快捷方式。
除了自我。类之外,您还可以从实例访问类数据,只要您没有隐藏变量。 inspect.stack()[1] [3]是当前函数的函数名。您可以使用它们来创建例外属性。