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();
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.
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.
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.
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.
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.
Your code as far as I can tell would not work.
__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__
.
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.
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
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With