Sidestepping Python’s reload() Function without Restarting Maya
The more complicated my tools get, the more modules I end up spreading them across. The tool that I’m working on currently consists of around 80 separate modules which makes the code nicely organised and easy to maintain, but there is a one down side, reloading the tool cleanly.
While I’m working on the tool I want to be able to edit any one of these 80 modules and have their changes visible the next time I open it, however Python will not reload a previously imported module unless you explicitly tell it to reload. The result is that you’ve made a change, restarted the tool and everything acts exactly like it did before.
Normally you get around this with simply reloading the module at startup. This is probably very familiar to you:
This is fine if you’re working with a simple script, but as your tool starts to branch out to multiple modules, with class-inheritance across modules, the amount of reloads you need to call to can get unwieldy.
Exploring the reload() Method
What I wanted was to effectively reload the tool in a way that mimicked my only other alternative at the time, reloading Maya. Obviously reloading Maya every time I wanted to see a new change in my tool is a huge time sink, I needed to find a better way.
Early on a colleague of mine suggested a perfectly valid method, of having a single script that you call that reloads all modules in a multi-page script. You’d put this in it’s own module and call it once when you launch the startup script.
This worked well with small amounts of reloads, but started to have problems the as the complexity increased. Reloading the modules in the wrong order broke a lot of the class inheritance in my tool. Without knowing the exact order that the modules in your tool needed to be reloaded, in order to not break their functionality quickly got difficult to track.
So at this point we’re still back to reloading Maya to get a reliable reload of the tool.
I briefly experimented with ways of recursively trawling through the script, mapping out the order to reload everything. I found a few modules online which had a go at this, as well as trying to roll my own but I just couldn’t get a reliable outcome.
Re-creating a Fresh Maya Session
I decided to think about this problem from another angle. If what I want to do is replicate restarting Maya, why don’t I just try putting the Maya session back to how it was before I started the tool?
I started with a pretty bad solution, storing a list of all the loaded modules pre-launch, making another list post-launch and then clearing the list when the tool closed. This is all fine and dandy until your tool asserts and the list isn’t reliable anymore. Time to think again.
I’m no stranger to brute force so I thought, why not kill everything?
This kills everything that isn’t an init_module. Maybe going a bit far. It’s burning the entire forest down to roast my marshmallow.
Narrowing Down the Task
So I thought I’d go for something a little more targeted, just removing the modules that I wanted to reload:
This method is a happy middle ground between blatting out all of the modules and having to carefully reload() modules in order. You can pick exactly the directory of modules that you want removed from the session and the next time you open the tool it will be as if they were being loaded for the very first time.
This has probably saved me a few hours of Maya restarts and a few grey hairs along the way.
Thanks for reading.