I am constantly running into issues where a rogue userSetup.py breaks my Maya startup. Unfortunately this means that I have to spend quite a bit of time playing detective. Maya logging does not start outputting the log until a certain point in the startup process. So often times the errors don’t appear in the log. I wish that more developers wrapped userSetup scripts in a way that not only prevented startup issues but also provided feedback.
A possible solution would be to wrap the startup in a function that handles such issues:
import maya.cmds as cmds
def user_setup_safe(user_setup_function):
from inspect import stack
try:
script_path = stack()[1][1]
cmds.evalDeferred(f"print(\"Running userSetup script from {script_path}\")")
user_setup_function()
except Exception as e:
cmds.evalDeferred(f"print(\"Error occured while running userSetup.py from {script_path}\")")
cmds.evalDeferred(f"print(\"{str(e)}\")")
#prompt dialog
cmds.confirmDialog(
title='userSetup.py Error!',
message=f'userSetup path: {script_path}\n\n{str(e)}',
button=['OK'],
defaultButton='OK',)
Would love to hear from other who dealt with this issue and came up with other solutions.
we’ve suffered from this before, but it’s not caused us too much headache because the errors do appear, just not in the Script Editor where you maybe expecting them. You should find they show up in the Output Window, so if you check there you should be able to spend way less time playing detective.
If you can ensure that you launch maya with a consistent command line, you can at least put a global exception handler in place which will catch any errors in the userSetup. You’d need a script which runs in the startup itself, called with the -c or -s flags; a good trick if you don’t already have a studio launcher is just a mel file called “launcher.mel” which users double click.
In any case if you can get something like this to run from the startup command line:
import logging
import traceback
import maya.utils
'''
Set up a special logger for the boot process
'''
BASE_MAYA_EXCEPT_HOOK = maya.utils.formatGuiException
_bootstrap_logger = logging.getLogger('ul.bootstrap')
# this writes to the output window; you could add
# a filehandler to log to a file instead or in addition.
_bootstrap_window_handler = logging.StreamHandler(sys.__stdout__)
_bootstrap_window_handler.setFormatter(logging.Formatter("boot: %(message)s"))
_bootstrap_logger .setLevel(logging.DEBUG)
_bootstrap_logger .addHandler(_bootstrap_window_handler)
def _startup_exception_hook(etype, value, tb, detail=2):
results = ["=" * 80] + traceback.format_exception(etype, value, tb, detail)
_bootstrap_logger .critical("\n%s" % "\n".join(results))
return BASE_MAYA_EXCEPT_HOOK(etype, value, tb, detail)
maya.utils.formatGuiException = _startup_exception_hook
"""
to undo the exception echo, you can do
maya.utils.formatGuiException = BASE_MAYA_EXCEPT_HOOK
"""
The problem, of course, is that if you have to worry about users who are doing their own thing at the userSetup stage you are probably also dealing with users who will cheat on your launcher. On a purely social level, I’d add something to your vanilla environment that allowed users to include their own stuff from some other location (like some folder or file you allow) in a way that’s guaranteed to run after your setup routine is complete. You could also collect data on what custom stuff people are trying to add and audit it for safety and/or possible malware.
If users go out of their way to mess with initialization things will never be stable.