In this post, I will talk about reloading scripts in Maya without restarting.
Preface
Xwift is a shelf that contains specialized scripts when I was producing my animated film. I want to write some blogs to document them, in case there’s anyone out there that needs some inspiration.
Everything is developed and tested using Maya 2022.
Swift is not (well, not yet) open-source and therefore I will not share the whole script in my post. However, after reading my posts I believe you can implement your own, given some time and effort.
Introduction
Here’s a simple problem that I encountered when developing scripts and tools:
Say you found out that you wrote a bug in your script after firing up Maya. So you fixed the bug and overwrote the problematic script using a fixed one. Turns out there isn’t a easy way to reload specific script (or all of them) in Maya. Your bug will remain there unless you restart Maya.
Such procedure is tolerable, but soon become tiresome if you are the person developing the script.
What’s more, sometimes you want to reload a couple of scripts at the same time, since it is very common in order to fix a certain problem, multiple scripts need modification.
Surprisingly, I can’t find any post online that talk about thi s problem. Maybe other people have a better way of doing it?
Assuming everything else works fine, and the scripts you wrote and is currently testing are the ones that is causing trouble. It is natural that we want to write a tool that reload all the scripts we developed, but not everything else so everything reloads (almost) instantly.
Tip: Not relevant, but disabling big packages like bifrost during startup in Maya greatly improves the start time. Coming back to my point, you don’t want to reload bifrost every single time when doing a reload, that will make each reload freeze for at least a couple seconds even on a fast NVMe SSD.
Goal
What we want is simple, write a script (That can later be tied to a button in our shelf) to reload a list of custom scripts.
Implementation
Step 1: Importing Necessary Libraries
There are two libraries that we need in this script:
import importlib
import maya.cmds as cmds
Step 2: Importing All Custom Scripts
Assuming you placed all your python scripts under a directory that Maya can find during startup:
You will need to import them as well. For example, script_1.py
is imported as script_1
.
import script_1
import script_2
import script_3
import ...
Step 3: Reloading Scripts
Here’s the main takeaway: The function we use to reload a script is importlib.reload()
.
Let’s write a couple lines that does nothing but reloading scripts one by one.
importlib.reload(script_1)
importlib.reload(script_2)
importlib.reload(script_3)
...
Step 4: Reloading the main shelf
Reloading the main shelf is a bit different, and instead of using importlib.reload(xwift_shelf)
, which is sometimes troublesome, here’s a better way:
Recall that the line inside userSetup.py
that loads our shelf when Maya starts is:
cmds.evalDeferred("import xwift_shelf; xwift_shelf.xwiftshelf()")
We can certainly use that here to reload our shelf and that prevents any weird issues.
Here’s some extra information that might be relevant about cmds.evalDeferred()
:
Although Python, the language we used to script our tools, supports multi-thread execution, Maya does not.
That means Maya can and only can do one thing at a time.
cmds.evalDeferred()
essentially is just “Finish whatever Maya is doing at the moment before executing this command.”
It’s just a safer way to do things.
Step 5: Write a GUI to let the human know it is done.
You don’t necessarily need to do this, but since reloading these python scripts is very fast, it takes less than a blink of an eye. It’s better to let the human know that it’s done reloading. Simply:
cmds.confirmDialog(title='Xwift Reload',
message='Xwift shelf and scripts reloaded successfully!',
button=['Okie!'], defaultButton='Okie!', dismissString='Okie!')
Step 6: Failsafe
Just as a good practice, although in an ideal world it’s not necessary, I wanted to make sure our script handles any unexpected exceptions.
We’ll wrap everything we mentioned above in a try except structure to catch any exceptions. The entire thing becomes:
try:
importlib.reload(script_1)
importlib.reload(script_2)
importlib.reload(script_3)
cmds.evalDeferred("import xwift_shelf; xwift_shelf.xwiftshelf()")
cmds.confirmDialog(title='Xwift Reload',
message='Xwift shelf and scripts reloaded successfully!',
button=['Okie!'], defaultButton='Okie!', dismissString='Okie!')
except Exception e:
print("[Reload Shelf] Failed to attempt reloading scripts:" + str(e))
Conclusion
Remember: Nothing is too small to make a difference. I hope this is helpful.
If you want to quickly say hi just shoot me a message using the contact portal.