我使用了一个装饰器类来装饰一个Exception,但是,似乎异常似乎无法使用确切的异常类进行例外处理。使用functools.update_wrapper更新装饰器类也不起作用。
class ClsDecor(object):
def __init__(self,cls):
self.cls=cls
self.counter=0
def __call__(self,*args):
self.counter+=1
return self.cls(*args)
@ClsDecor
class Err(Exception):
def __init__(self):
Exception.__init__(self)
try:
raise Err()
except Err as e:
print 'catched'
except Exception as e:
print 'Not catched'
答案 0 :(得分:2)
首先,方法__call__
应为:
def __call__(self, *args):
return self.cls(*args)
您的代码会在__call__
内引发错误并直接转到print 'Not catched'
,这是第一级错误。修复此错误后,您将达到类型不匹配的第二级错误,这在dhke的评论中得到了很好的解释。基本的想法是,Err
实际上是ClsDecor
之后的@ClsDecor
类型,但您在Err
中返回了原始类型__call__
的实例,这显然不匹配except Err
。您可以轻松地使用装饰器来存档您的目的,如:
def err_dec(Cls):
class NewErr(Exception):
def __init__(self, *args, **kwargs):
self.err = Cls(*args, **kwargs)
return NewErr
@err_dec
class Err(Exception):
def __init__(self):
Exception.__init__(self)
更新了评论中的要求:
def err_dec(Cls):
class NewErr(Exception):
c = 0
def __init__(self, *args, **kwargs):
NewErr.c = NewErr.c + 1
self.err = Cls(*args, **kwargs)
def counter(self):
return NewErr.c
return NewErr
@err_dec
class Err(Exception):
def __init__(self):
Exception.__init__(self)
try:
Err()
Err()
raise Err()
except Err as e:
print e.counter()
print 'catched'
except Exception as e:
print 'Not catched'
答案 1 :(得分:0)
问题不在于装饰。也许装饰让你困惑,但这不是问题。
您需要了解Err
是什么。 Decorator的工作方式与普通定义类似,但在分配名称之前将装饰器应用于对象。这就等同于:
class Err(Exception):
def __init__(self):
Exception.__init__(self)
Err = ClsDecor(Err)
现在Err
是一个ClsDecor
实例,在提升它时你将调用实例(而不是类),你将调用ClsDecor.__call__
(而不是{ {1}})。当你尝试使用参数(ClsDecor.__init__
)调用self.cls
时会发生错误,但args
是self.cls
,它不会接受任何其他参数(除了Err
)。
如果您在默认的self
子句中打印了错误,您会看到这一点。如果你点击默认条款,打印错误是一个好主意,因为它常常是因为你遇到了意外的异常:
except
或许你根本不应该抓住它 - 如果没有发现异常,那么无论如何都会打印回溯。
答案 2 :(得分:0)
在所有人的帮助下,我终于得到了这样的解决方案:
class ErrMetaClass(type):
def __new__(mcls,cls_name,cls_parents,cls_attr):
return super(ErrMetaClass,mcls).__new__(mcls,
cls_attr['_cls'].__name__, cls_parents,cls_attr)
def err_dec(cls):
class NewErr(Exception):
__metaclass__ = ErrMetaClass
_cls=cls
c=0
def __init__(self):
NewErr.c+=1
return NewErr
@err_dec
class Err(Exception):
def __init__(self):
Exception.__init__(self)
try:
raise Err()
except Err as e:
print Err.c
except Exception as e:
print type(e)