EXCEPTION HANDLING |
Mari Extension Pack registers its own Exception handler to
sys.excepthook
Below you can find information about how to interact with Extension Pack's Exception handler.
Extension Pack logs errors originating from its tools (only its own tools) via the Exception Handler.
Error Logs are stored as separate files alongside the Mari Log and are grouped by month
- Win: C:\Users\<USERNAME>\Documents\Mari\Logs\MEPLog_{MachineName}_{Month}_{Year}.txt
- Linux: /home/<USERNAME>/Mari/Logs/MEPLog_{MachineName}_{Month}_{Year}.txt
Example of a Extension Pack Bug Log
The new Exception Handler is configured to try to continue calling previously registered Exception Handlers, by saving the previously registered Exception Hook before
registering its own
self.old_excepthook = sys.excepthook
When Extension Pack's Exception Hook is executed it then tries to forward the exception to the previous one, before executing its own handling.
def exception_hook(self, exc_type, exc_value, exc_traceback):
""" ..... """
if self.old_excepthook:
self.old_excepthook(exc_type, exc_value, exc_traceback)
You can gain access to the Main Class "UncaughtHook" registered to sys.excepthook, by calling
mari.ExtensionPack.exceptions.getExceptionHandlerClass()
The full source code of the class can be found further down this page.
On exception, two signals are emitted, that you can attach to
_exception_caught_log = QtCore.Signal(object)
_exception_caught_raw = QtCore.Signal(object,object,object)
- The _log Signal carries the string for Extension Pack's own Log Files
- The _raw Signal carries the raw exception (exc_type, exc_value, exc_traceback)
exception_handler = mari.ExtensionPack.exceptions.getExceptionHandlerClass()
exception_handler._exception_caught_raw.connect(myFunctionCall)
While not recommended, it is possible to disable the registering of the custom exception hook to sys.excepthook.
To do so set the Environment Variable below to True or 1.
- MARI_EP_PREVENT_EXCEPTION_LOGGING
class UncaughtHook(QtCore.QObject):
_exception_caught_log = QtCore.Signal(object)
_exception_caught_raw = QtCore.Signal(object,object,object)
def __init__(self, *args, **kwargs):
super(UncaughtHook, self).__init__(*args, **kwargs)
Prevent_EP_Logging = False
try:
Prevent_EP_Logging = os.environ['MARI_EP_PREVENT_EXCEPTION_LOGGING']
except:
pass
if not Prevent_EP_Logging:
# this registers the exception_hook() function as hook with the Python interpreter
self.old_excepthook = sys.excepthook
sys.excepthook = self.exception_hook
# calls the Extension Pack Function handling writing of the log files
self._exception_caught_log.connect(exception_handler)
def exception_hook(self, exc_type, exc_value, exc_traceback):
"""Function handling uncaught exceptions.
It is triggered each time an uncaught exception occurs.
Also calls the previous non-EP exception handler if it exists.
"""
if self.old_excepthook:
self.old_excepthook(exc_type, exc_value, exc_traceback)
if issubclass(exc_type, KeyboardInterrupt):
# ignore keyboard interrupt to support console applications
sys.__excepthook__(exc_type, exc_value, exc_traceback)
else:
exc_info = (exc_type, exc_value, exc_traceback)
log_msg = '\n'.join([''.join(traceback.format_tb(exc_traceback)),
'{0}: {1}'.format(exc_type.__name__, exc_value)])
log.critical("Uncaught exception:\n {0}".format(log_msg), exc_info=exc_info)
# trigger signals
self._exception_caught_log.emit(log_msg)
self._exception_caught_raw.emit(exc_type, exc_value, exc_traceback)