import subprocess import dataExporter #this is the script I want to run remotely import sys import os.path paths = sys.path rootPath = None for path in paths: if os.path.exists(path + "\\Maya.exe"): rootPath = path + "\\mayapy.exe" break scriptPath = dataExporter.__file__ myVar = "Hello World" command = '{0} {1} {2}'.format(rootPath, scriptPath, myVar) mayaVar = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) subprocess.Popen.wait(mayaVar) a, b = mayaVar.communicate() if mayaVar.returncode: print b else: print a
First of all, I need to give credit to Henry Foster for a wonderful post that allowed me to clarify the use of subprocess and how to get the data from it. Here is his original post.
Now I'll take a bit to clarify what I am doing in the code. The first part:
paths = sys.path rootPath = None for path in paths: if os.path.exists(path + "\\Maya.exe"): rootPath = path + "\\mayapy.exe" breakThis piece of code simply figures out where your location for mayapy.exe is. Pretty straight forward. Now for some fun stuff:
scriptPath = dataExporter.__file__ myVar = "Hello World" command = '{0} {1} "{2}"'.format(rootPath, scriptPath, myVar) mayaVar = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) subprocess.Popen.wait(mayaVar) output, errors = mayaVar.communicate() if not mayaVar.returncode: print output else: print errorsHere I am looking for the full path to the script I am going to run in the subprocess, and then initialize the subprocess itself. The "mayaVar" variable holds for us the output that that happens inside the subprocess. As you can see from the code, I am passing to the subprocess first the location of mayapy.exe, then the location of the script I want mayapy to run, and then I pass it the single variable that the script is going to accept. I also open up the PIPE from the subprocess to send and receive values between our mayapy. Then comes a rather important part of the script where I request the subprocess to wait for itself to finish the job. Now that part isnt' always necessary. However, my tool needed for the exported data to be available to continue, so I couldn't allow maya to just go on. If the wait method is not envoked, your subprocess will run just fine, but the output values from the mayaVar will not be available right away. In some cases, i.e. batch exporting, you probably don't even want to wait as you might be doing some other logic after the batch has been sent off. Keep in mind that invoking wait() will cause maya to stall and wait for the output from your subprocess and hence will not allow any user interaction during that time. Once my data is exported I check whether the process was a success at all, and if any errors were thrown. That is done via subprocess' "returncode": 1 - True, some errors have occured, 0 - False, nothing went wrong, all is good (I found this quite unintuitive at start, but got used to it). Now once your process is done, you can assign the subprocess outputs to some variables. And finally here is the actual variation of the 'dataExporter' file that can give you some sort of output:
import sys import pymel.core as pm def replyToMessage(message): reply = "" if message == "Hello World": reply = "Hello to you too!" elif message == "Goodbye": reply = "Leaving already? Ah well, take care!" else: reply = "I am sorry, not sure what you just said..." sys.stdout.write(reply) return reply if __name__ == "__main__": replyToMessage(sys.argv[1])By just importing the pymel.core you initialize a specialized maya.standalone. The 'sys.stdout.write' will write you the output that you will get back. Keep in mind, all of the feedback you get will be in string format. I do not think there is any way to pass more complex data between this script being run and the current maya session you are running as a user without any socket connection. Anyway, hope someone finds this helpful at some point! Till next time, DK
Thank you for this post!
ReplyDeleteThis one line fixed the main bug in my own batch manager and change everything in my work:
import pymel.core as pm
I don't realy understand, why it works, but thank you once more!
Hey, you are very welcome. Yea, the pymel import seems to do some of it's own little bit of magic that fixes all this 'standalone' stuff. Very glad you found this useful!
DeleteThanks for the post.
ReplyDeleteI tried this but had no luck yet. Running your example code worked out but when it come to loading a file the maya standalone instance crashes:
pymel.internal.factories : INFO : MFnDagNode.model is deprecated
Warning: file: C:/PROGRA~1/Autodesk/Maya2014/scripts/startup/initialStartup.mel line 192: Y-axis is already the Up-axis
pymel.internal.startup : ERROR : could not perform Maya initialization sequence: failed on namedCommandSetup.mel: Error occurred during execution of MEL script
How are you doing this?
Thanks, Andi