Reputation: 21
Two newly installed from the same scratch VMs with the same python36 versions have different values for sys.path:
1st VM
[root@vm1 ~]# python36 -m site
sys.path = [
'/root',
'/usr/lib64/python36.zip',
'/usr/lib64/python3.6',
'/usr/lib64/python3.6/lib-dynload',
'/usr/lib64/python3.6/site-packages',
'/usr/lib/python3.6/site-packages',
]
USER_BASE: '/root/.local' (doesn't exist)
USER_SITE: '/root/.local/lib/python3.6/site-packages' (doesn't exist)
ENABLE_USER_SITE: True
2nd VM
[root@vm2 ~]# python36 -m site
sys.path = [
'/root',
'/usr/lib64/python36.zip',
'/usr/lib64/python3.6',
'/usr/lib64/python3.6/lib-dynload',
'/usr/local/lib64/python3.6/site-packages',
'/usr/local/lib/python3.6/site-packages',
'/usr/lib64/python3.6/site-packages',
'/usr/lib/python3.6/site-packages',
]
USER_BASE: '/root/.local' (doesn't exist)
USER_SITE: '/root/.local/lib/python3.6/site-packages' (doesn't exist)
ENABLE_USER_SITE: True
2nd VM has /usr/local/lib* paths for some reasons.
os.environ on both machines shows the same values for variables:
original PATH variables(dunno if they are connected to PYTHONPATH) are also the same
[root@vm1 ~] env | grep -E "^PATH=" PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/opt/java/latest/bin:/opt/java/latest/jre/bin:/root/bin
How python36 initialise PYTHONPATH(sys.path) during initial installation, when no custom values at OS side for PYTHONPATH are configured?
Upvotes: 1
Views: 1391
Reputation: 365587
A normal installation is expected to be able to run without any PYTHONPATH
environment variable at all. As explained in the docs, PYTHONPATH
is there for the user, to…
Augment the default search path for module files. The format is the same as the shell’s PATH: one or more directory pathnames separated by os.pathsep (e.g. colons on Unix or semicolons on Windows). Non-existent directories are silently ignored.
So, none of the standard Python installers (that includes building locally and running make install
, and the Windows and macOS binary installers available under Downloads at python.org) do anything at all to create a PYTHONPATH
value or get it set up in your environment. And most semi-official and third-party packages (like the Pythons includes or packaged by Linux distros and by Apple, the less-common-platforms installers under Downloads/Other, "batteries plus" Python distributions like Anaconda, etc.) will work the same way.
Notice that the PYTHONPATH
directories are added to the default search path. As noted in the same docs:
The default search path is installation dependent, but generally begins with prefix/lib/pythonversion (see PYTHONHOME above). It is always appended to PYTHONPATH.
An additional directory will be inserted in the search path in front of PYTHONPATH as described above under Interface options. The search path can be manipulated from within a Python program as the variable sys.path.
This is also explained in sys.path
:
A list of strings that specifies the search path for modules. Initialized from the environment variable PYTHONPATH, plus an installation-dependent default.
As initialized upon program startup, the first item of this list, path[0], is the directory containing the script that was used to invoke the Python interpreter. If the script directory is not available (e.g. if the interpreter is invoked interactively or if the script is read from standard input), path[0] is the empty string, which directs Python to search modules in the current directory first. Notice that the script directory is inserted before the entries inserted as a result of PYTHONPATH.
…
See also Module
site
This describes how to use .pth files to extend sys.path.
Unlike PYTHONPATH
, this site
mechanism is sometimes used by third-party and semi-official installs. For example, Apple uses it to add its Extras
library of pre-installed packages like pyobjc
to the builtin Python 2.7 on macOS.
If you're wondering how that "installation-dependent default" is loaded by the sys
module in CPython, it ultimately comes down to a public C API function, Py_GetPath
:
Return the default module search path; this is computed from the program name (set by Py_SetProgramName() above) and some environment variables. The returned string consists of a series of directory names separated by a platform dependent delimiter character. The delimiter character is ':' on Unix and Mac OS X, ';' on Windows. The returned string points into static storage; the caller should not modify its value. The list
sys.path
is initialized with this value on interpreter startup; it can be (and usually is) modified later to change the search path for loading modules.
If you want to see how the C code works, you probably want to start at _PyPathConfig_Init
, because the actual Py_GetPath
just calls a function that makes sure this has been called and then pulls the value out of the struct that it sets.
Upvotes: 2