Source code for cgl.plugins.maya.standalone
import sys
import subprocess
import os
import importlib
import pickle
from traceback import format_exception
import tempfile
try:
import unreal
except:
unreal = None
MAYAPY = "C:\\Program Files\\Autodesk\\Maya2024\\bin\\mayapy.exe"
[docs]
def test_func():
return "test result"
[docs]
class MayaStandAloneException(Exception):
pass
[docs]
def rebuild_exc(exc, tb):
exc.__cause__ = MayaStandAloneException(tb)
return exc
[docs]
class MayaStandAloneExceptionPickle(object):
def __init__(self, exc, tb):
tb = ''.join(format_exception(type(exc), exc, tb))
self.exc = exc
# Traceback object needs to be garbage-collected as its frames
# contain references to all the objects in the exception scope
self.exc.__traceback__ = None
self.tb = '\n"""\n%s"""' % tb
def __reduce__(self):
return rebuild_exc, (self.exc, self.tb)
[docs]
class MayaStandAloneResult:
def __init__(self):
self.exc = None
self.result = None
[docs]
def main_maya(result_file):
ret = MayaStandAloneResult()
try:
in_data = sys.stdin.buffer.read()
entrypoint, args, kwargs = pickle.loads(in_data)
print(entrypoint, args, kwargs)
module_name, func_name = entrypoint.split(":")
from maya import standalone
standalone.initialize(name='python')
from maya import cmds
print(cmds.about(p=True))
# import cgl.plugins.maya.userSetup
module = importlib.import_module(module_name)
func = getattr(module, func_name)
ret.result = func(*args, **kwargs)
except BaseException as e:
# you have to do some funky stuff to pass a exception through pickle
ret.exc = MayaStandAloneExceptionPickle(e, e.__traceback__)
with open(result_file, 'wb') as f:
pickle.dump(ret, f)
[docs]
def run_in_maya_standalone(entrypoint, *args, **kwargs):
"""
run a function in maya standalone process and return result
entrypoint is a string with following syntax:
"cgl.plugins.maya.module_name:func_to_run"
the ':' at the end is the function you want to run in the module
args and kwargs need to be pickleable objects and as does the result of the function
"""
module_name, func_name = entrypoint.split(":")
in_data = pickle.dumps([entrypoint, args, kwargs])
with tempfile.TemporaryDirectory() as tmp_dirname:
result_file = os.path.join(tmp_dirname, "result").replace("\\", '/')
cmd = [MAYAPY, '-c', f"from cgl.plugins.maya import standalone; standalone.main_maya('{result_file}');"]
print(subprocess.list2cmdline(cmd))
proc = subprocess.Popen(cmd,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE if unreal else None,
stderr=subprocess.PIPE if unreal else None)
out, err = proc.communicate(in_data)
if proc.returncode:
raise RuntimeError(f"Subprocess stderr:\n" + err.decode() if err else "")
if not os.path.exists(result_file):
raise RuntimeError("maya did not write a result file")
with open(result_file, 'rb') as f:
ret = pickle.load(f)
if ret.exc:
raise ret.exc
return ret.result
if __name__ == "__main__":
# r = run_in_maya_standalone("cgl.plugins.maya.standalone:test_func")
r = run_in_maya_standalone("maya.cmds:sphere")
print(r)