Run Maya Batch Mode in 2023!

I’m reviving a post from exactly 4 years ago ⌛️. It was severely flawed since it was one of my earliest post while I’m still learning my ways around Maya.

Standalone Module

1
2
import maya.standalone
maya.standalone.initialize(name='python')

Using mayapy Interpreter

I strongly recommend using mayapy in order to stay consistent with the behaviour of GUI maya.

Prefer using mayapy: Maya’s own python interpreter, this ensures all the libraries and plugins are compatible, it also saves some trouble configuring environments.

Using External Python Interpreter

When using external interpreter for whatever reason, we’ll need to check:

  • The python interpreter should match the maya python version

    • e.g. (python27 for Maya 2018)
  • System environment variable will need to set up in order to find maya modules

    • Otherwise, we may encounter the following:
    1
    ImportError: No module named maya.standalone

To configure the environment for our external interpreter:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import sys
import os


MAYA_LOCATION = "C:/Program Files/Autodesk/Maya2018"
PYTHON_LOCATION = MAYA_LOCATION + "/Python/Lib/site-packages"

os.environ["MAYA_LOCATION"] = MAYA_LOCATION
os.environ["PYTHONPATH"] = PYTHON_LOCATION

sys.path.append(MAYA_LOCATION)
sys.path.append(PYTHON_LOCATION)
sys.path.append(MAYA_LOCATION+"/bin")
sys.path.append(MAYA_LOCATION+"/lib")
sys.path.append(MAYA_LOCATION+"/Python")
sys.path.append(MAYA_LOCATION+"/Python/DLLs")
sys.path.append(MAYA_LOCATION+"/Python/Lib")
sys.path.append(MAYA_LOCATION+"/Python/Lib/plat-win")
sys.path.append(MAYA_LOCATION+"/Python/Lib/lib-tk")
print('\n'.join(sys.path))

Making Our First Standalone Script

After maya.standalone has initialized, we can import maya.cmds as usual.

Let’s add a test function to our standalone script.

1
2
3
4
5
6
7
8
9
10
11
12
13
import maya.cmds as cmds

def test():
maya_file_to_open = r"C:\Users\Lei\Desktop\test.ma"
cmds.file(maya_file_to_open, o=True)

# import a file and rename
maya_file_to_import = r"C:\Users\Lei\Desktop\import.ma"
cmds.file(maya_file_to_import, i=True, type="mayaAscii")

temp_name = r"C:\Users\Lei\Desktop\temp.ma"
cmds.file(rename=temp_name)
cmds.file(force=True, save=True, options='v=1;p=17', type='mayaBinary')

This test function opens a maya file on my desktop and import a maya file and save out as another file.

Execution

Here I’m using mayapy as example, we can of course using the external python interpreter, but again, it takes extra steps.

Execute from Command Line

  • make sure to add mayapy to our system environment variable.

    • in system variable: add C:\Program Files\Autodesk\Maya2018\bin to Path
  • open command prompt, and enter mayapy [directoryTo/firstStandalone.py]

Execute using subprocess

We can do it without going to command line, but by executing another .py using subprocess

1
2
3
4
5
6
7
8
9
10
11
12
import subprocess

mayapy = r'C:\Program Files\Autodesk\Maya2018\bin\mayapy.exe'
script = r'[directory/firstStandalone.py]'

process = subprocess.Popen(
[mayapy, script],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
env=env
)
out, error = process.communicate()

Here I’m removing the environment setup in firstStandlone.py, and add a wrapper:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import logging
import traceback


import maya.standalone
maya.standalone.initialize(name='python')

import maya.cmds as cmds


def test():
maya_file_to_open = r"C:\Users\Lei\Desktop\test.ma"
cmds.file(maya_file_to_open, o=True)

# import a file and rename
maya_file_to_import = r"C:\Users\Lei\Desktop\import.ma"
cmds.file(maya_file_to_import, i=True, type="mayaAscii")

temp_name = r"C:\Users\Lei\Desktop\temp.ma"
cmds.file(rename=temp_name)
cmds.file(force=True, save=True, options='v=1;p=17', type='mayaBinary')


if __name__ == '__main__':
try:
cmds.evalDeferred(runMode)
except:
logging.error(traceback.print_exc())

Standalone Script with Arguments

Sometimes, we would want to pass arguments to our standalone script

Using sys.argv

1
2
3
4
import sys

file_path = sys.argv[1]
file_name = sys.argv[2]

Example from Toadstorm Nerdblog:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import subprocess


maya_path = 'directory/mayapy.exe' # mayapy or full path to mayapy.exe
script_path = 'directory/firstStandalone.py'


def add_layer(file_names,layer_name):
for file_name in file_names:
command = r'mayapy {} {} {}'.format(
script_path, file_name, layer_name
)

process = subprocess.Popen(
command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
process.wait()
print(process.returncode) # this return the message from cmd


if __name__ == '__main__':
# define a list of filenames to iterate through
files = ['file1', 'file2', 'file3']
render_layer = 'a new render layer'

# run procedure, assuming you've already defined it
add_layer(files, render_layer)

Using argparser

In the commandline launch script, add argment:

1
2
3
4
5
6
7
8
9
10
11
12
import subprocess

...
scene = r"C:\Users\Lei\Desktop\test.ma"

process = subprocess.Popen(
[mayapy, script, 'scene={}'.format(scene)],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
env=env
)
out, error = process.communicate()

And then in the wrapper, use the ArgumentParser()

1
2
3
4
5
6
7
8
9
10
11
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('scene')

command_line_args = parser.parse_args()
SCENE = command_line_args.scene

def example():
cmds.file(SCENE, open=True, force=True)
...

Bonus: Integrate UI Elements from Qt

It is easy to integrate UI in a standalone tool by creating a QApplication instance, and for Maya GUI, Maya has QApplication instance already created.

but for maya standalone script, we need to make sure to create a QApplication instance before the standalone initialization:

1
2
3
4
5
6
7
8
9
10
11
import sys

from Qt import QtWidgets


app = QtWidgets.QApplication(sys.argv)

import maya.standalone
maya.standalone.initialize()

...

Depending on our tool need, usually standalone script wouldn’t block the main event loop, so we just exit when finished, therefore, no need to add sys.exit(app.exec_())

Bonus: Copying GUI Maya Environment

To get the exact environment as the GUI Maya version (this could be useful if there’s any startup scripts that modifies the environment)

In the maya session, parse out the environment and save it as a dictionary:

1
2
3
import os

env_dict = dict(os.environ)

And in the commandline setup .py, apply the environment from the dictionary:

1
2
3
4
5
6
7
8
9
10
env_dict_copy_from_maya = {'TEST': 'THIS IS A TEST'}

current_env = os.environ.copy()
for key, value in env_dict_copy_from_maya.items():
current_env[key] = value

process = subprocess.Popen(
...,
env=current_env
)

Reference

Xingyu Lei - Save Time and Boost Efficiency: Learn to Run Maya in Batch Mode

Stack Overflow - maya standalone with pyside2

Tech-Artist Org - Import maya.standalone problem

Stack Overflow - use external python script to open maya and run another script inside maya

Stack Overflow - How to use an external interpreter for Maya?

Toadstorm Nerdblog - Python in Maya Standalone