Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python decorated exception cant be excepted

I used a decorator class to decorate an Exception, but, it seems that, the exception seems to be unable to be excepted with the exact exception class. Use functools.update_wrapper to update the decorator class doesn't work either.

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'
like image 438
Max Avatar asked Jun 03 '26 20:06

Max


1 Answers

First of all, method __call__ should be:

def __call__(self, *args):
    return self.cls(*args)

Your code will raise an error inside __call__ and brought you directly to print 'Not catched', this is the first level error. After fixing this error, you'll reach the second level error of type mismatch, which is well-explained in comment by dhke. Basic idea is that Err is actually type ClsDecor after @ClsDecor, but you return an instance of raw type Err in __call__, which is obvious not matched with except Err. You can easily use an decorator to archive your purpose like:

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)

Updated for requirement in comment:

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'
like image 129
shizhz Avatar answered Jun 06 '26 10:06

shizhz