Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a hook function every time an Exception is raised

Let's say I want to be able to log to file every time any exception is raised, anywhere in my program. I don't want to modify any existing code.

Of course, this could be generalized to being able to insert a hook every time an exception is raised.

Would the following code be considered safe for doing such a thing?

class MyException(Exception):

    def my_hook(self):
        print('---> my_hook() was called');

    def __init__(self, *args, **kwargs):
        global BackupException;
        self.my_hook();
        return BackupException.__init__(self, *args, **kwargs);


def main():
    global BackupException;
    global Exception;

    BackupException = Exception;
    Exception = MyException;

    raise Exception('Contrived Exception');


if __name__ == '__main__':
    main();
like image 245
AgentLiquid Avatar asked Jun 22 '09 20:06

AgentLiquid


People also ask

What happens when you raise an exception?

Raising an exception is a technique for interrupting the normal flow of execution in a program, signaling that some exceptional circumstance has arisen, and returning directly to an enclosing part of the program that was designated to react to that circumstance.

Does increasing exception stop execution?

except block is completed and the program will proceed. However, if an exception is raised in the try clause, Python will stop executing any more code in that clause, and pass the exception to the except clause to see if this particular error is handled there.

What is the significance of using raise ValueError exception block?

The function will raise the ValueError when an invalid argument value will be passed to the function. The try-except block will catch the ValueError passed from the function and print the error message.

What is an raising exception in Python with example?

As a Python developer you can choose to throw an exception if a condition occurs. To throw (or raise) an exception, use the raise keyword.


2 Answers

If you want to log uncaught exceptions, just use sys.excepthook.

I'm not sure I see the value of logging all raised exceptions, since lots of libraries will raise/catch exceptions internally for things you probably won't care about.

like image 68
Ken Avatar answered Sep 29 '22 09:09

Ken


Your code as far as I can tell would not work.

  1. __init__ has to return None and you are trying to return an instance of backup exception. In general if you would like to change what instance is returned when instantiating a class you should override __new__.

  2. Unfortunately you can't change any of the attributes on the Exception class. If that was an option you could have changed Exception.__new__ and placed your hook there.

  3. the "global Exception" trick will only work for code in the current module. Exception is a builtin and if you really want to change it globally you need to import __builtin__; __builtin__.Exception = MyException

  4. Even if you changed __builtin__.Exception it will only affect future uses of Exception, subclasses that have already been defined will use the original Exception class and will be unaffected by your changes. You could loop over Exception.__subclasses__ and change the __bases__ for each one of them to insert your Exception subclass there.

  5. There are subclasses of Exception that are also built-in types that you also cannot modify, although I'm not sure you would want to hook any of them (think StopIterration).

I think that the only decent way to do what you want is to patch the Python sources.

like image 39
Cosmin Stejerean Avatar answered Sep 29 '22 09:09

Cosmin Stejerean