Where is Python's sys.path initialized from? Where is Python's sys.path initialized from? python python

Where is Python's sys.path initialized from?


Python really tries hard to intelligently set sys.path. How it isset can get really complicated. The following guide is a watered-down,somewhat-incomplete, somewhat-wrong, but hopefully-useful guidefor the rank-and-file python programmer of what happens when pythonfigures out what to use as the initial values of sys.path,sys.executable, sys.exec_prefix, and sys.prefix on a normalpython installation.

First, python does its level best to figure out its actual physicallocation on the filesystem based on what the operating system tellsit. If the OS just says "python" is running, it finds itself in $PATH.It resolves any symbolic links. Once it has done this, the path ofthe executable that it finds is used as the value for sys.executable, no ifs,ands, or buts.

Next, it determines the initial values for sys.exec_prefix and sys.prefix.

If there is a file called pyvenv.cfg in the same directory assys.executable or one directory up, python looks at it. DifferentOSes do different things with this file.

One of the values in this config file that python looks for isthe configuration option home = <DIRECTORY>. Python will use this directory instead of the directory containing sys.executablewhen it dynamically sets the initial value of sys.prefix later. If the applocal = true setting appears in thepyvenv.cfg file on Windows, but not the home = <DIRECTORY> setting,then sys.prefix will be set to the directory containing sys.executable.

Next, the PYTHONHOME environment variable is examined. On Linux and Mac,sys.prefix and sys.exec_prefix are set to the PYTHONHOME environment variable, ifit exists, superseding any home = <DIRECTORY> setting in pyvenv.cfg. On Windows,sys.prefix and sys.exec_prefix is set to the PYTHONHOME environment variable,if it exists, unless a home = <DIRECTORY> setting is present in pyvenv.cfg,which is used instead.

Otherwise, these sys.prefix and sys.exec_prefix are found by walking backwardsfrom the location of sys.executable, or the home directory given by pyvenv.cfg if any.

If the file lib/python<version>/dyn-load is found in that directoryor any of its parent directories, that directory is set to be to besys.exec_prefix on Linux or Mac. If the filelib/python<version>/os.py is is found in the directory or any of itssubdirectories, that directory is set to be sys.prefix on Linux,Mac, and Windows, with sys.exec_prefix set to the same value assys.prefix on Windows. This entire step is skipped on Windows ifapplocal = true is set. Either the directory of sys.executable isused or, if home is set in pyvenv.cfg, that is used instead forthe initial value of sys.prefix.

If it can't find these "landmark" files or sys.prefix hasn't beenfound yet, then python sets sys.prefix to a "fallback"value. Linux and Mac, for example, use pre-compiled defaults as thevalues of sys.prefix and sys.exec_prefix. Windows waitsuntil sys.path is fully figured out to set a fallback value forsys.prefix.

Then, (what you've all been waiting for,) python determines the initial valuesthat are to be contained in sys.path.

  1. The directory of the script which python is executing is added to sys.path.On Windows, this is always the empty string, which tells python touse the full path where the script is located instead.
  2. The contents of PYTHONPATH environment variable, if set, is added to sys.path, unless you'reon Windows and applocal is set to true in pyvenv.cfg.
  3. The zip file path, which is <prefix>/lib/python35.zip on Linux/Mac andos.path.join(os.dirname(sys.executable), "python.zip") on Windows, is added to sys.path.
  4. If on Windows and no applocal = true was set in pyvenv.cfg, then the contents of the subkeys of the registry keyHK_CURRENT_USER\Software\Python\PythonCore\<DLLVersion>\PythonPath\ are added, if any.
  5. If on Windows and no applocal = true was set in pyvenv.cfg, and sys.prefix could not be found, then the core contents of the of the registry key HK_CURRENT_USER\Software\Python\PythonCore\<DLLVersion>\PythonPath\ is added, if it exists;
  6. If on Windows and no applocal = true was set in pyvenv.cfg, then the contents of the subkeys of the registry keyHK_LOCAL_MACHINE\Software\Python\PythonCore\<DLLVersion>\PythonPath\ are added, if any.
  7. If on Windows and no applocal = true was set in pyvenv.cfg, and sys.prefix could not be found, then the core contents of the of the registry key HK_CURRENT_USER\Software\Python\PythonCore\<DLLVersion>\PythonPath\ is added, if it exists;
  8. If on Windows, and PYTHONPATH was not set, the prefix was not found, and no registry keys were present, then therelative compile-time value of PYTHONPATH is added; otherwise, this step is ignored.
  9. Paths in the compile-time macro PYTHONPATH are added relative to the dynamically-found sys.prefix.
  10. On Mac and Linux, the value of sys.exec_prefix is added. On Windows, the directorywhich was used (or would have been used) to search dynamically for sys.prefix isadded.

At this stage on Windows, if no prefix was found, then python will try todetermine it by searching all the directories in sys.path for the landmark files,as it tried to do with the directory of sys.executable previously, until it finds something.If it doesn't, sys.prefix is left blank.

Finally, after all this, Python loads the site module, which adds stuff yet further to sys.path:

It starts by constructing up to four directories from a head and a tail part. For the head part, it uses sys.prefix and sys.exec_prefix; empty heads are skipped. For the tail part, it uses the empty string and then lib/site-packages (on Windows) or lib/pythonX.Y/site-packages and then lib/site-python (on Unix and Macintosh). For each of the distinct head-tail combinations, it sees if it refers to an existing directory, and if so, adds it to sys.path and also inspects the newly added path for configuration files.


"Initialized from the environment variable PYTHONPATH, plus an installation-dependent default"

-- http://docs.python.org/library/sys.html#sys.path