Contents:
What import does
Temporarily add a new directory to import from
Permanently add a new directory to import from
Make import work like MEL source
Since importing modules is important to understand and anyone first learning how to use Python will need to do this. I figured I would go over how to properly import python modules in Maya. I will go through examples of how to temporarily add a path to your sys.paths so that Python can find it and I will show how to add the path permanently. Last I give an example of a function I made so you can just pass it a path and it returns the module that was imported for you to work with.
First thing you learn with Python scripts is you can not use the menu item file/source script in the Maya script editor. I dont know why Maya shows you both .mel files and .py files since sourcing a .py file will only give you errors. Basically the point here is you dont source Python files. It wont work.
The way you import a python script is admittedly a bit more cumbersome than sourcing a MEL file. Python does not allow you to simply source a given path name to the file. This is not a Maya specific issue, but how python is designed.
Also importing a python script or module is not the same as sourcing in other ways. When you use import, Python checks to see if the module is loaded and if it is not it will read the module and create the data in a namespace. Python also compiles a .pyc file. So thats why you see extra files in your folder after importing a module. If the module has been changed after it was imported and you want to “source” that version then the correct code to use is:
reload( module )
When you import a python script you are to simply do this:
# import the filename into its own namespace with the same name import module # import the filename into its own namespace with a specified name import module as newname # Import all the definitions and variables of the module into the global namespace # This defeats the purpose of Python making your code less modular so it should rarely be used from module import * # Reference specific variables and definitions into the global namespace from the module from module import varA, varB # Allows a variable to be passed to import and returns the module to a variable you specify # The way this works is a bit odd since even if foo is imported you cant call foo.defname() # you must in this case use the variable mod to call mod.defname() mod = __import__( module )
It is not ok to type a file extension or a path name. You can not even use a variable with the correctly named string. You can however use __import__() if you want to give it a variable. I show an example of this later. When you import, Python will look for the script in a set of system paths that Python finds. Python looks in its standard module library paths and also includes the PYTHONPATH environment variable paths.
Maya also automatically adds these paths by default:
C:/Documents and Settings/Ryan Trowbridge/My Documents/maya/2008/prefs/scripts
C:/Documents and Settings/Ryan Trowbridge/My Documents/maya/2008/scripts/
C:/Documents and Settings/Ryan Trowbridge/My Documents/maya/scripts
It is important to note that Maya will not find any scripts in your /My Documents/maya/2008/scripts/ folder. Note that the path has an extra forward slash therefore Python finds nothing. I think the Maya programmers are to blame for that one. This might be fixed in Maya 2009. If you place your script in the /My Documents/maya/scripts path Python files will import fine. From reading on the boards some people seem to be confused about this and I think rightfully so. Thankfully you can fix this with the environment variable as I show later.
First lets look at what paths Python is looking for using the script editor. Open up your Maya script editor and in a python tab execute this code:
import sys # sys.path is simply an array of system paths that gets created when you first start up maya syspaths = sys.path for path in syspaths: print path
As long as you have not modified the sys.path or PYTHONPATH enviroment variable by default you should see something like this:
C:\Program Files\Autodesk\Maya2008\bin C:\Program Files\Autodesk\Maya2008\bin\python25.zip C:\Program Files\Autodesk\Maya2008\Python\DLLs C:\Program Files\Autodesk\Maya2008\Python\lib C:\Program Files\Autodesk\Maya2008\Python\lib\plat-win C:\Program Files\Autodesk\Maya2008\Python\lib\lib-tk C:\Program Files\Autodesk\Maya2008\bin C:\Program Files\Autodesk\Maya2008\Python C:\Program Files\Autodesk\Maya2008\Python\lib\site-packages C:/Documents and Settings/Ryan Trowbridge/My Documents/maya/2008/prefs/scripts C:/Documents and Settings/Ryan Trowbridge/My Documents/maya/2008/scripts/ C:/Documents and Settings/Ryan Trowbridge/My Documents/maya/scripts
Now its fairly simple to just add a new path to the sys.path so that Python will look there. This is only temporary though since Maya reconstructs this path list every time you launch Maya. Here is an example of adding a new path to the sys.path.
First add a file to C:\test called rtPrintSomething.py and inside this file add this:
def rtTest(): print 'hello'
After creating that file execute this:
import sys # Add a new path to the sys path while Maya is still open # this will be lost when you restart Maya sys.path.append( 'C:/test' ) syspaths = sys.path import rtPrintSomething rtPrintSomething.rtTest()
There are three ways to add paths to your PYTHONPATH.
1. You can edit your Windows environment variables and add the PYTHONPATH variable with the paths you want to add. You can do this temporarily if needed in some cases using windows Command Prompt with:
set PYTHONPATH=”C:/foo”
This will not be remembered when you close the Command Prompt. You can do it permanently by adding a new enviroment variable by right clicking on your “My Computer” and selecting properties. Now select the “Advanced” tab. Then select the “Enviroment Variables” button. Now to add the PYTHONPATH select the “New” button in the “System variables” section.
I wouldn’t recommend doing it this way, but it can be done and you need to know that it can because this will overwrite your Maya.env files PYTHONPATH if defined like this. So its good to know.
2. Another way to add a path for Python to find when importing is to setup your userSetup.py file which should be located here:
C:\Documents and Settings\user\My Documents\maya\version\scripts
The file is not created by default but you can create a new file called userSetup.py and in it you can create a short script to add the paths just like I showed earlier like this:
import sys
sys.path.append( ‘C:/test’ )
If you need more paths added just append more as needed. You can also do other things in this file to help setup your enviroment like if you wanted to do this:
import maya.OpenMaya as om
This would let you always have OpenMaya imported when you start Maya. Thats getting off topic though.
3. The last way you can edit your PYTHONPATH is by adding to the environment variable to your Maya.env file. Go to your My Documents folder, the path should look something like this:
C:\Documents and Settings\Ryan Trowbridge\My Documents\maya\2008
Open the Maya.env file located in this folder using a text editor and add this line:
PYTHONPATH = C:/testB
This is generally what development studios use so that everyone shares the same environment paths. If you need to add two paths use the semicolon like this:
PYTHONPATH = C:/testB;C:/testC;
Do not add a space after the semicolon or Maya will not read any paths after the space. Once this has been edited, restart Maya and try this in your script editor:
import sys syspaths = sys.path for path in syspaths: print path
The script editor should print something like this:
C:\Program Files\Autodesk\Maya2008\bin C:/testB C:\Program Files\Autodesk\Maya2008\bin\python25.zip C:\Program Files\Autodesk\Maya2008\Python\DLLs C:\Program Files\Autodesk\Maya2008\Python\lib C:\Program Files\Autodesk\Maya2008\Python\lib\plat-win C:\Program Files\Autodesk\Maya2008\Python\lib\lib-tk C:\Program Files\Autodesk\Maya2008\bin C:\Program Files\Autodesk\Maya2008\Python C:\Program Files\Autodesk\Maya2008\Python\lib\site-packages C:/Documents and Settings/Ryan Trowbridge/My Documents/maya/2008/prefs/scripts C:/Documents and Settings/Ryan Trowbridge/My Documents/maya/2008/scripts/ C:/Documents and Settings/Ryan Trowbridge/My Documents/maya/scripts
Before this next example I created a folder here c:/testC With a file called rtPrintSomething3.py in it with the code:
def rtTest(): print 'hello'
With the above knowledge you can write a simple function to automate importing a script at a specific path.
import sys import os # This imports the given filepath and returns the module as an object def importPath( filepath ): file = os.path.basename( filepath ) dir = os.path.dirname( filepath ) toks = file.split( '.' ) modname = toks[0] sys.path.append( dir ) # This version of python import lets you use variables as the name # The default version does not module = __import__( modname ) # This returns module as an object return module # Give the importPath function a path module = importPath( 'c:/testC/rtPrintSomething3.py' ) # Now you can use the variable module which is pointing to the module of rtPrintSomething3 module.rtTest()
And last but not lest, the following code is the closest I could get to MEL’s source command.
import sys
import os
"""
Here is a function that I made that works very similarly to the MEL source command
If a full path is passed to psource it will check if the path is part of sys.path and
if not it will add it. If only the module name is passed to filepath it will import that
module and not add anything to sys.path Either way this function will import and reload
the module so that you know it is freshly updated
"""
def psource( module ):
file = os.path.basename( module )
dir = os.path.dirname( module )
toks = file.split( '.' )
modname = toks[0]
# Check if dirrectory is really a dirrectory
if( os.path.exists( dir ) ):
# Check if the file dirrectory already exists in the sys.path array
paths = sys.path
pathfound = 0
for path in paths:
if(dir == path):
pathfound = 1
# If the dirrectory is not part of sys.path add it
if not pathfound:
sys.path.append( dir )
# exec works like MEL's eval but you need to add in globals() at the end to make sure
# the file is imported into the global namespace else it will only be in the scope of this function
exec ('import ' + modname) in globals()
# reload the file to make sure its up to date
exec( 'reload( ' + modname + ' )' ) in globals()
# This returns the namespace of the file imported
return modname
# When you first import a file you must give it the full path
psource( 'c:/testC/rtPrintSomething3.py' )
rtPrintSomething3.rtTest()
# Now you can edit the file and add a new definition
# After using psource the directory will already be added to sys.path so you can just psource
# the module which will reload the module
psource( 'rtPrintSomething3' )
Cheers,
-RyanT
October 24th, 2009 at 3:21 am
Thanks a lot for the detailed info.
Cheers
May 3rd, 2010 at 1:14 pm
yup - cheers for this…. just spent ages trying to use the maya source option..
June 20th, 2010 at 10:26 am
Thank you so much! I spent an hour trying to figure out why it wasn’t reading files from /maya/2008/scripts/ … so silly >.<