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)