Search code examples
pythonexceptionmaya

Maya - Automatically run function on an uncaught exception


I am trying to build a function that runs only when uncaught exceptions are raised.

A solution that I found online is to override / wrap sys.excepthook, like this:

import sys


def exception(*args, **kwargs):
    print('Uncaught exception was found', args, kwargs)


sys.excepthook = exception


def foo():
    bar()


def bar():
    raise ValueError('I am an exception. Catch me if you can!')


foo()

If you save the above code into a file and run it using python, it will print "Uncaught exception was found". And if you add a try/except around bar(), it doesn't run. This is exactly the functionality that I want.

This even works in an interactive Python shell and using mayapy. The only situation that I've found it does not work is within Autodesk Maya itself. You can run the above code in the Script Editor, as a menu item, or as a shelf button and it does not run the contents of the exception function. Oddly enough, it does work in Nuke however (both using its python interpreter and from inside of Nuke).

So to summarize - the above method works by:

  • Saving the text as a file and executing it with python
  • Running python as an interactive shell, pasting the code and running it in there
  • Saving the text as a file and executing it with mayapy
  • Running mayapy as an interactive shell, pasting the code and running it in there

And doesn't work by:

  • Running the code in the Maya Script Editor or as a shelf button or menu item.

If there's another, better method to achieve what I want then please let me know. Otherwise, is there a reason why this technique isn't working? Any help would be appreciated.


Solution

  • IMO it would be cleaner to let meddling with excepthook to interactive shells and instead wrapping your main in a try/except and then just reraise the exception after your special treatment like so:

    def main():
        foo()
    
    try:
        main()
    except Exception as e:
        print(f'Uncaught exception was found:   {type(e).__name__}: {e}')
        raise
    

    But if you like to go with excepthook, this blog describes a solution for maya:

    import maya.utils
    
    def myExceptCB(etype, value, tb, detail=2):
    
        # do something here...
    
        print "do something here..."
    
        return maya.utils._formatGuiException(etype, value, tb, detail)
    
    maya.utils.formatGuiException = myExceptCB