Capturing mayapy.exe results?

Hey all,

I’m currently in a pipeline of Maya 2009 (python 2.5) and MotionBuilder 2010 (python 2.6). Because of the python version differences, I am unable to communicate python to python between these two apps.

This leaves me with system calls to mayapy.exe. If from MoBu I call mayapy.exe, passing in a module script with a list return value, mayapy.exe will execute the code then return a numeric exit code from the system call, and not the results of the list (which I can verify it has when printing to stdout).

What is the best way to handle information handoff between two different versions of python? I can think of numerous .txt file and even system variable hacks I like to avoid if at all possible.

Thanks for any input you guys have!
-csa

this is probably a horrible misuse of sys.exit (if it even works), but you might be able to get away with something like this:

import os
import sys

def return_list():
    the_list = os.listdir(r'D:\dev')

    return the_list

if __name__=='__main__':
    sys.exit(return_list())

Otherwise you could maybe try Popen.communicate?

Don’t think of this as a python problem- this is the most fundamental of inter-process communication problems. There are many potential solutions for this sort of thing, from complex frameworks like WCF, to simpler solutions like named pipes. I’d suggesting researching IPC strategies in python and choosing what works for you- I’d highly discourage a ‘hacky’ approach when you have the ability to do something more stable (which, because you’re using python, you do).

*(We do a ‘hacky’ approach to communicate via morpheme’s lua and python, and sometimes photoshop/javascript and .NET, but it was a last resort).

Last Motion Builder <> Maya pipe I did wrote out a temp file to disk, I found it to be the most stable solution and ultimately the easiest to implement, you also get a de facto message|error log with that file so tracking down errors in the process is easier. This approach was partly due to what I could pass into a motion builder batch call though if I remember correctly …

[QUOTE=djTomServo;8457]this is probably a horrible misuse of sys.exit (if it even works), but you might be able to get away with something like this:

import os
import sys

def return_list():
    the_list = os.listdir(r'D:\dev')

    return the_list

if __name__=='__main__':
    sys.exit(return_list())

Otherwise you could maybe try Popen.communicate?[/QUOTE]

I ended the day yesterday with Popen.communicate, passing a module to mayapy.exe from MoBu. This solution does allow me to retrieve return values from Maya, but it appears to ultimately make it’s way back into MoBu as a return value converted to a unicode string. I’ll assume if we were using 2010 version of both apps, I could avoid mayapy.exe all together and keep return values as python objects. Today I was going to mess with decoding the string return values and see where I get.

-csa

Ok, I think I got this working now.

The sys.exit() did end up sending data over from Maya, but again this data was returned 1) As a string I’d have to decode and 2) along with some other spew from mayapy.exe which I didn’t really want and 3) classified as an ‘error’ which I felt would be confusing down the road.

What I ended up finding while googling your suggestions is the cPickle module.

I use subprocess to call mayapy.exe from MoBu, passing a python file as the argument. The python file (argument) performs the Maya query, then pickles the results to a text file on disk. I then read the pickle output into MoBu. Now I have all the data I need, in the exact data construct my Maya python file collected. Also cool to note, is that since Maya uses mayapy.exe as a middle-man, I am able to communicate between two different versions of python (2.6 —> 2.5 --> 2.6).

Here are some example supporting files to demonstrate. (I haven’t implemented them fully, but they should hopefully demonstrate where I’m going with this):

MoBu_Requst.py


'''
Example:  Send a query to Maya using mayapy.exe from MoBu
'''
import os, subprocess

# apparently this is necessary with Maya 2009 according to the internets
os.chdir('C:/Program Files/Autodesk/Maya2009/bin')

# Call MayaTest.test() from MoBu through subprocess
mayapy = subprocess.Popen(["C:/Program Files/Autodesk/Maya2009/bin/mayapy.exe", "c:/scripts/MayaTest.py"],stderr=subprocess.PIPE, stdout=subprocess.PIPE)
output, errors = mayapy.communicate()

MayaTest.py


'''
Example:  Opens a specific Maya file containing some joints.  All joints in the
file are picked to c:/mayapy_outfile.txt
'''
import cPickle
import maya.standalone
maya.standalone.initialize( name='python' )

import maya.cmds as cmds

def test():

    cmds.file( 'c:/Test/JointTest.mb', o=True)
    
    uResult = cmds.ls( type='joint' )
    sResult = [str(r) for r in uResult]
    
    FILE = open("c:/mayapy_output.txt", 'w')
    cPickle.dump( sResult, FILE )
    FILE.close()
    
if __name__ == "__main__":
    test()

MoBu_Decode.py


'''
Example:  Loads the pickeled results from Mobu_Request into a
variable named results
'''

import cPickle
results = []

FILE = open("c:/mayapy_output.txt", 'r')
results = cPickle.load(FILE)
FILE.close

print results

Thanks everyone for their help. If anyone has any comments on this, do share!

-csa