How does Maya populate its maya.cmds package?
From over on my Mel Wiki:
When using Python in Maya, to access the bulk of the mel commands via Python, you import the mel.cmds
package, usually into a namespace, like so:
import maya.cmds as mc print mc.ls()
But if you browse to that package on disk, you’ll find it empty, only containing an __init__.py
file (required for package creation):
C:\Program Files\Autodesk\Maya<VERSION>\Python\Lib\site-packages\maya\cmds
So how are all the ‘mel commands’ added to that package for execution in Python?
There is a Maya startup Python module living here, that works the magic of populating that package:
C:\Program Files\Autodesk\Maya<VERSION>\Python\Lib\site-packages\maya\app\commands.py
It inspects a file called commandList
(no extension, but it’s text) living here:
C:\Program Files\Autodesk\Maya<VERSION>\bin\commandList
You can open that file in a text editor, and what you’ll find are two columns: One with a ‘mel’ command name, and one with a .dll where that command ‘lives’. Those .dll’s live in the same dir as the commandList
file. Here’s a sample:
TanimLayer AnimSlice.dll about Shared.dll addAttr Shared.dll addDynamic DynSlice.dll addPP DynSlice.dll affectedNet Shared.dll affects Shared.dll agFormatIn Translators.dll agFormatOut Translators.dll aimConstraint AnimSlice.dll air DynSlice.dll aliasAttr Shared.dll align Shared.dll
What commands.py
does is parse the commandList
file and append each command (via a Python command wrapper function) to maya.cmd
‘s ‘__dict__
‘ attribute (maya.cmds.__dict__
), which is the lookup table users access when calling their favorite mel command via Python (like maya.cmds.ls()
) It also passes the name of the .dll to the command wrapper function, so when the user executes the given command, it first loads the parental .dll.
Crack open commands.py
for the nitty-gritty details.
If you want to see the end result of all this hard work, you can run this code in Maya. But it prints a *lot* of stuff:
import maya.cmds as mc for k in sorted(mc.__dict__.keys()): print k, mc.__dict__[k]
I have to disagree with commands.py. You can remove that python file completly with no affect. In fact other then the __init__.py files maya only needs python.py in site-packagesmayaapp from the entire pythonlib directory
Technically you are correct, but Maya is still running either commands.pyc or commands.pyo in its absence. Did you also try removing them? They’re all interrelated. In actuality there’s a good chance Python isn’t even looking to commands.py (since it doesn’t change once installed on your computer) for execution: commands.pyc (bytecode compiled) or commands.pyo (optimized bytecode) would be the one Python actually accesses. Try removing those other modules: When I do, while I can still ‘import maya.cmds’ in Maya, any of the commands I try to execute after that have no effect:
import maya.cmds as mc
print mc.ls()
# nothing, usually a big list…
So while I didn’t mention commands.pyc or commands.pyo in the above post (since they’re a bit more ‘behind the scenes’ of how Python works), I figured the generic usage of commands.py would be sufficient.
I did test it with .pyc and .pyo files removed with the same results. Because we are removing commands.py code down the line basic.py and gui.py no longer get executed so the stdout no longer runs through maya. You should still be getting output in maya ‘output window’. Also any executable commands like polySphere are visibly working as well.
Interesting: I hadn’t checked the command window, and sure enough, the data does show up in there. So ok, I’ll agree with you now 😉
So this brings up two questions:
#1 Why are you monkeying with this start-up stuff? Just a general query 😉
#2 How DOES maya.cmds get populated then…..?
Just when you thought you had something figured out…
Just trying to figure it out myself. Have no solution yet.
Hmph, it made me rather curious after reading the post – had a bit of a play and not really much to report aside from the fact that maya.cmds is a fat empty module, but then everything after that (i.e. maya.cmds.polySphere) is a builtin of the module object.. which kinda suggests that there’s some hardlinking going back in maya-land.
Actually.. more detail, just had a brainwave. No extra use, but more edification:
Fire up mayapy.exe (i’m on windows right now)
>>> import maya.cmds
# works ok
>>> maya.cmds.polySphere()
# no go.
>>>import maya.standalone
>>>maya.standalone.initialize()
# startup msgs removed
>>>maya.cmds.polySphere()
[u’pSphere’1,u’polySphere1′]
and of course, maya.standalone is inside the \site-packages\maya\standalone.pyd file which i can’t really crack open, where all the magic appears to occur. The earliest i can patch in would be in maya\app\startup\basic.py at which point, it’s already done with maya.cmds. I suspect the processCommandList() call is just going through and doing proper housekeeping (or patching in esoteric modules which aren’t already loaded.. I’ll bet polySpheres are part of a core set..)
Ah well. Fun exercise in hunting round though 😀