This subject is about batching Maya files in a session of Maya other than the one that is currently open, via Python. It's one thing to (via the currently opened Maya) loop over a list of files opening them in succession and executing code. But if you want to launch external Maya's in batch mode (so as to not disturb your current Maya session), open a file, and execute code on that file (all in Python), it's a different story.
To batch file via Maya with mel, it's pretty straightforward via
Different methods below. I came up with Method C first, got suggested Method B, then sort of combined the two to come up with Method A.
I'll label each thing has it's executed so you can see the data flow.
GUI mode starts with GUI A and ends with GUI D, which then starts BATCH A and ends with BATCH E.
Make a batch script:
Then make the python module it calls to:
Key Components: (the file-names aren't important, just illustrating the example)
Here is a bit of code from
http://docs.python.org/library/subprocess.html
This is the guts of our wrapper mel script. All it does is call to the Python code we care about:
To batch file via Maya with mel, it's pretty straightforward via
maya.exe
:> maya -batch -file someMayaFile.ma -command someMelProcThere is
mayapy.exe
as well, but this doesn't launch Maya: It launches Maya's version of Python. It is a Maya mirror of python.exe
. However, once it has been launched, Maya itself can be imported in as a Python module, and then batching can take place. Method A explains this below.Different methods below. I came up with Method C first, got suggested Method B, then sort of combined the two to come up with Method A.
Method A
The example below will batch over all the passed in Maya files, and saves a new group node in them as proof it worked. Some of the magic is usingsubprocess.call
to call to mayapy.exe
, and passing in an additional argument that is the name of the current file to work on. Another bit of trickery is having the module do double-duty: When executed in GUI Maya the user runs its main() function to start it up, but when it is called to via mayapy.exe
putting it in 'batch mode', the top & bottom section 'if __name__ == "__main__":
' are executed as well which both imports maya.standalone
(thus now physically has Maya running inside of mayapy.exe
) and calls to the batchOperation()
function, which can then query, via sys.argv
the command-line arguments passed in (which are the names of the files to batch over). I have a feeling that's not terribly clear. I hope the code makes more sense ;)I'll label each thing has it's executed so you can see the data flow.
GUI mode starts with GUI A and ends with GUI D, which then starts BATCH A and ends with BATCH E.
# batchTest.py import subprocess if __name__ == "__main__": # If we're in 'batch' mode, it means that mayapy.exe is running, # so load maya.standalone into it: import maya.standalone maya.standalone.initialize(name='python') # If you have a userSetup.py that is needed for happy Maya execution, call # to it here: import userSetup userSetup.main() import maya.cmds as mc def main(paths): """ Launched in the gui version of Maya, manually, or via some other script. Parameters : paths : string\list : Path(s) to Maya files to batch over. """ if not isinstance(paths, list): paths = [paths] args = ['mayapy', __file__, '-'] args.extend(paths) # This fires off another version of Maya in 'batch' mode, calling back to # this code, executing the 'batch only' parts. Luckily, the current version # of Maya calling it waits for the other version to complete doing it's thing # before continuing on in this code... subprocess.call(args) def batchOperation(): """ The work done by the batch: This has been called to while Maya is in batch mode, via the subprocess.call() func in the main() function: Because of this, we capture the incoming args via sys.argv. A single instance of Maya is launched, and then all the files are batched over in that instance, and processed """ # The sys.argv vals match the subprocess call above # sys.argv[0] : The path to this module ( __file__ ) # sys.argv[1] : '-' # sys.argv[2] + : Path(s) to the files to batch over paths = sys.argv[2:] # If there is an error, the shell will just disappear. So we wrap it in a # try\except, allowing it to stay open to help track down bugs. try: mc.file(prompt=False) for fil in paths: mc.file(fil, force=True, open=True) mc.group(empty=True, name='I_was_made_in_batch_mode', world=True) mc.file(force=True, save=True) except Exception, e: print "Exception:", e raw_input("Encountered an exception, see above. Press Enter to exit...") finally: mc.file(prompt=True) # When called to via batch mode, run this code. This line must come after the # function it's calling. if __name__ == "__main__": batchOperation()To run in Maya:
import batchTest batchTest.main(['c:/temp/myFileA.ma', 'c:/temp/myFileB.ma'])You should see a shell pop up for the new instance of Maya that is launched (via mayapy.exe), and then each path is opened and batch processed in that shell. The gui version of Maya will wait until completion of the batch to continue on with its code.
Method B:
This (modified) example was given to me by Keir Rice. Thanks Keir!Make a batch script:
batchTest.bat
. It runs mayapy.exe
, which is Maya's version of Python.REM Launcher batch file: batchTest.bat "%ProgramFiles%\Autodesk\Maya2010\bin\mayapy.exe""c:\temp\test.py" pause
- Add
pause
to the end of the batch script if you want the shell to stay open upon completion.
Then make the python module it calls to:
# python script to run: c:\temp\test.py import maya.cmds def TestFunction(): print maya.cmds.about(version=True) if __name__ == "__main__": # Init Maya: import maya.standalone maya.standalone.initialize(name='python') # If you have one: import userSetup userSetup.main() # Run your code: TestFunction()Finally, run the bat script. Results should be printed in the shell.
Method C:
This is one I came up with before I knew about Method A or B, above.Key Components: (the file-names aren't important, just illustrating the example)
mainModule.py
: This is the Python module that orchestrates the whole thing. It can be executed from Maya, or the command line.melScript.mel
: This is a 'wrapper' script that our batch operation will call to. It in turn, via the melpython
command, will execute the Python code we want to have effect the scene files.pythonModule.py
: This is the Python module that our mel script calls to. In this example, it executes themain()
function inside.
Here is a bit of code from
mainModule.py
. By calling to subprocess.call()
, we're able to launch Maya in batch mode on a specific file, executing our wrapper mel command on it:http://docs.python.org/library/subprocess.html
# mainModule.py import subprocess subprocess.call(['maya', '-batch', '-file', 'c:\\myFile.ma', '-command', 'melScript'])
This is the guts of our wrapper mel script. All it does is call to the Python code we care about:
// melScript.mel global proc melScript(){ python("import pythonModule"); python("pythonModule.main()"); }
pythonModule.py
and its main()
function can prettymuch do whatever you'd like to that scene file:# pythonModule.py import maya.cmds as mc def main(): # do stuff!