Catch exceptions inside a class

后端 未结 3 864
别跟我提以往
别跟我提以往 2020-12-29 06:53

Is it possible to write an exception handler to catch the run-time errors generated by ALL the methods in class? I can do it by surrounding each one with try/except:

相关标签:
3条回答
  • 2020-12-29 07:10

    Assuming you've got a decorator catch_exception as in @Jon Clement's answer...

    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
    

    The metaclass applies catch_exception to everything that appears to be a method while it is defining Test.


    In response to a comment regarding custom messages for each method, one could attach such a message (or even a callback function to generate a message) as an attribute:

    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"
    

    The catch_exception decorator would look for a msg attribute on its argument and use it, if found, in handling the exception.

    This approach could be extended; instead of a string, msg could be a mapping of exception types to strings. In either case, the string could be replaced (with support from catch_exception, of course) with an arbitrary callback function that takes, say, the raised exception as an argument.

    def calc_handler(exc):
        # ...
    
    calc.callback = calc_handler
    
    0 讨论(0)
  • 2020-12-29 07:18

    Warning: if you want something like this, it's likely you don't... but if you really want to...

    Something like:

    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()
    

    shows how to decorate individual functions. You can then create a class decorator to apply this decorator to each method (be careful of classmethod's/staticmethod's/properties etc...)

    0 讨论(0)
  • 2020-12-29 07:25

    A decorator would be a good solution here.

    Here's an example of how you could do it:

    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 on top of the function is a shortcut for f1 = catch_exception_decorator(f1).

    Instead of doing self.class, you could also access class data from the instance, as long as you're not shadowing variables. inspect.stack()[1][3] is the function name of the current function. You can use these to create the exception attributes.

    0 讨论(0)
提交回复
热议问题