Recipe2.21.Dynamically Changing the PythonSearch Path


Recipe 2.21. Dynamically Changing the PythonSearch Path

Credit: Robin Parmar

Problem

Modules must be on the Python search path before they can be imported, but you don't want to set a huge permanent path because that slows performanceso, you want to change the path dynamically.

Solution

We simply conditionally add a "directory" to Python's sys.path, carefully checking to avoid duplication:

def AddSysPath(new_path):     """ AddSysPath(new_path): adds a "directory" to Python's sys.path     Does not add the directory if it does not exist or if it's already on     sys.path. Returns 1 if OK, -1 if new_path does not exist, 0 if it was     already on sys.path.     """     import sys, os     # Avoid adding nonexistent paths     if not os.path.exists(new_path): return -1     # Standardize the path.  Windows is case-insensitive, so lowercase     # for definiteness if we are on Windows.     new_path = os.path.abspath(new_path)     if sys.platform == 'win32':         new_path = new_path.lower( )     # Check against all currently available paths     for x in sys.path:         x = os.path.abspath(x)         if sys.platform == 'win32':             x = x.lower( )         if new_path in (x, x + os.sep):             return 0     sys.path.append(new_path)     # if you want the new_path to take precedence over existing     # directories already in sys.path, instead of appending, use:     # sys.path.insert(0, new_path)     return 1 if _ _name_ _ == '_ _main_ _':     # Test and show usage     import sys     print 'Before:'     for x in sys.path: print x     if sys.platform == 'win32':           print AddSysPath('c:\\Temp')           print AddSysPath('c:\\temp')     else:           print AddSysPath('/usr/lib/my_modules')     print 'After:'     for x in sys.path: print x

Discussion

Modules must be in directories that are on the Python search path before they can be imported, but we don't want to have a huge permanent path because doing so slows down every import performed by every Python script and application. This simple recipe dynamically adds a "directory" to the path, but only if that directory exists and was not already on sys.path.

sys.path is a list, so it's easy to add directories to its end, using sys.path.append. Every import performed after such an append will automatically look in the newly added directory if it cannot be satisfied from earlier ones. As indicated in the Solution, you can alternatively use sys.path.insert(0, . . . so that the newly added directory is searched before ones that were already in sys.path.

It's no big deal if sys.path ends up with some duplicates or if a nonexistent directory is accidentally appended to it; Python's import statement is clever enough to shield itself against such issues. However, each time such a problem occurs at import time (e.g., from duplicate unsuccessful searches, errors from the operating system that need to be handled gracefully, etc.), a small price is paid in terms of performance. To avoid uselessly paying such a price, this recipe does a conditional addition to sys.path, never appending any directory that doesn't exist or is already in sys.path. Directories appended by this recipe stay in sys.path only for the duration of this program's run, just like any other dynamic alteration you might do to sys.path.

See Also

Documentation for the sys and os.path modules in the Library Reference and Python in a Nutshell.



Python Cookbook
Python Cookbook
ISBN: 0596007973
EAN: 2147483647
Year: 2004
Pages: 420

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net