This post applies to Maya, but MotionBuilder as well (or any Python based application).
The other day I wanted to source a Python script into Maya and he took me few minutes to realize there was no easy/automatic way to do this in Maya other than loading the script into the Maya Script editor and run it unlike with MEL and the source command where you can give the full path name of the MEL script.
Fine, but I wanted to do it from an application. Why that? I usually reply to that question why not ;)
No seriously, imagine you got Maya already running, you download a script, you got the choice to copy it to one of the Maya user' profile 'scripts' folders, and then using MEL, or C++ source the Python script using import. But what if you put the script somewhere else?
I first thought, well that is easy - all Python needs is to have the PYTHONPATH setup properly, and MEL gives us an easy way to change it. Something along this lines:
{ string $py =`getenv PYTHONPATH` ; string $me ="/MyPath/scripts" ; string $test =`match $me $py` ; if ( $test == "" ) { if ( `about -nt` ) { $py +=";" + $me ; } else { $py +=":" + $me ; } putenv PYTHONPATH $py ; } }
The code is between {} to avoid global namespace clashing, but the getenv/putenv approach does not work, when you do a 'import myscript' you'll get an error like this:
# Error: line 1: ImportError: file <maya console> line 1: No module named myscript #
But if you read the Python documentation, that is supposed to work :(
The trick is that, maybe MEL updates the PYTHONPATH, but the Python engine did not saw the change. If you now run this code:
import sys for item in sys.path: print item
You won't see your new path, and this is why it does not work. So instead of doing the pure MEL code, you need to do it from Python, but then this is 'The chicken or the egg causality dilemma' since to do it from Python we need to load our python script :(
Again MEL comes to the rescue, and you can run this code instead:
{ string $me ="/MyPath/scripts" ; python ("import sys") ; string $py[] =python ("sys.path") ; if ( stringArrayCount ($me, $py) == 0 ) python ("sys.path.insert(0, '" + $me + "')") ; }
And next time you do 'import myscript', that will work just fine.
From that we could easily create a command to temporary add a path, source the python script into the Python engine as Python will never load again the script once it is loaded, even if you 'import' it again. In Maya you need to use 'reload' or 'force' in Python.
For the anecdote, we now have a scientific proof from genetic studies, that the egg was first %\
Just curious - why did you went through all the MEL trouble when it's just "import sys; sys.path.append(r'/MyPath/scripts')" in a Python tab?
Posted by: Viktoras Makauskas | February 25, 2013 at 02:07 PM
Hi Viktoras
You're absolutely right, if you got a change to put that code in a button, menu, shelves - you do not need that. But if you are in C++ (without using Python C++ libs), .NET, then you're locked. The are other situation where you would need this too, and I'll explain in more details in a future post.
-cyrille
Posted by: Cyrille Fauvel | February 26, 2013 at 09:34 AM