>>> import site
>>> site.getsitepackages()
['/usr/local/lib/python3.9/site-packages', '/usr/lib/python3/site-packages', '/usr/lib/python3.9/site-packages']
>>> site.getusersitepackages()
'/home/xxx/.local/lib/python3.9/site-packages'
Debian specificity
Debian packages a modified Python interpreter
which looks system site in /usr/lib/python3/dist-packages
instead of /usr/lib/python3/site-packages
.
Also, pip
will install with --user
by default.
Example
% pwd
/tmp/plop-2335880
% PYTHONPATH=/foo:/bar python -m site
sys.path = [
'/tmp/plop-2335880', ← current directory
'/foo', ← PYTHONPATH
'/bar', ← PYTHONPATH
'/usr/lib/python39.zip', ← standard lib
'/usr/lib/python3.9', ← standard lib
'/usr/lib/python3.9/lib-dynload', ← standard lib
'/home/xxx/.local/lib/python3.9/site-packages', ← user site
'/usr/local/lib/python3.9/dist-packages', ← system-local site
'/usr/lib/python3/dist-packages', ← system site
'/usr/lib/python3.9/dist-packages', ← system site
USER_BASE: '/home/xxx/.local' (exists)
USER_SITE: '/home/xxx/.local/lib/python3.9/site-packages' (exists)
ENABLE_USER_SITE: True
Limiting options
The Python interpreter has options.
python -s
(equivalent to setting $PYTHONNOUSERSITE
) disables the user site:
% PYTHONPATH=/foo:/bar python -s -m site
sys.path = [
'/tmp/plop-2335880',
'/foo',
'/bar',
'/usr/lib/python39.zip',
'/usr/lib/python3.9',
'/usr/lib/python3.9/lib-dynload',
'/usr/local/lib/python3.9/dist-packages',
'/usr/lib/python3/dist-packages',
'/usr/lib/python3.9/dist-packages',
USER_BASE: '/home/xxx/.local' (exists)
USER_SITE: '/home/xxx/.local/lib/python3.9/site-packages' (exists)
ENABLE_USER_SITE: False
python -S
disables all sites:
% PYTHONPATH=/foo:/bar python -S -m site
sys.path = [
'/tmp/plop-2335880',
'/foo',
'/bar',
'/usr/lib/python39.zip',
'/usr/lib/python3.9',
'/usr/lib/python3.9/lib-dynload',
USER_BASE: '/home/xxx/.local' (exists)
USER_SITE: '/home/xxx/.local/lib/python3.9/site-packages' (exists)
ENABLE_USER_SITE: None
python -E
disables $PYTHONPATH
and $PYTHONHOME
:
sys.path = [
'/tmp/plop-2335880',
'/usr/lib/python39.zip',
'/usr/lib/python3.9',
'/usr/lib/python3.9/lib-dynload',
'/home/xxx/.local/lib/python3.9/site-packages',
'/usr/local/lib/python3.9/dist-packages',
'/usr/lib/python3/dist-packages',
'/usr/lib/python3.9/dist-packages',
USER_BASE: '/home/xxx/.local' (exists)
USER_SITE: '/home/xxx/.local/lib/python3.9/site-packages' (exists)
ENABLE_USER_SITE: True
python -I
combines -s
and -E
but also prevents current directory from being added:
% PYTHONPATH=/foo:/bar python -I -m site
sys.path = [
'/usr/lib/python39.zip',
'/usr/lib/python3.9',
'/usr/lib/python3.9/lib-dynload',
'/usr/local/lib/python3.9/dist-packages',
'/usr/lib/python3/dist-packages',
'/usr/lib/python3.9/dist-packages',
USER_BASE: '/home/xxx/.local' (exists)
USER_SITE: '/home/xxx/.local/lib/python3.9/site-packages' (exists)
ENABLE_USER_SITE: False
*.pth
When Python loads a site, it will load files with pth
extension to try to find additional paths.
Those files can either contain:
paths (or names) of more folders to add to path
example: ~/.local/lib/python3.9/site-packages/easy-install.pth
Python source code which may add entries to the path
example: <virtualenv>/lib/python3.9/site-packages/_virtualenv.pth
This lets the possibility to have arbitrary code run when the Python interpreter is started, by default, unless restrictive options are given (see above).
This can be a security threat since it makes it easy to inject malicious code into every Python program.
virtualenv
In a virtualenv created with --system-site-packages
:
% virtualenv --system-site-packages env-system
[...]
% . env-system/bin/activate
% PYTHONPATH= python -s -m site
sys.path = [
'/tmp/plop-2335880',
'/usr/lib/python39.zip',
'/usr/lib/python3.9',
'/usr/lib/python3.9/lib-dynload',
'/tmp/plop-2335880/env-system/lib/python3.9/site-packages',
'/usr/local/lib/python3.9/dist-packages',
'/usr/lib/python3/dist-packages',
'/usr/lib/python3.9/dist-packages',
USER_BASE: '/home/xxx/.local' (exists)
USER_SITE: '/home/xxx/.local/lib/python3.9/site-packages' (exists)
ENABLE_USER_SITE: False
The virtualenv has its own site dir (/tmp/plop-2335880/env-system/lib/python3.9/site-packages
),
in addition to the system site dirs (as --system-site-packages
let it point to the system).
In a virtualenv created without:
% virtualenv env-no-system
[...]
% . env-no-system/bin/activate
% PYTHONPATH= python -s -m site
sys.path = [
'/tmp/plop-2335880',
'/usr/lib/python39.zip',
'/usr/lib/python3.9',
'/usr/lib/python3.9/lib-dynload',
'/tmp/plop-2335880/env-no-system/lib/python3.9/site-packages',
USER_BASE: '/home/xxx/.local' (exists)
USER_SITE: '/home/xxx/.local/lib/python3.9/site-packages' (exists)
ENABLE_USER_SITE: False
See this PyCon 2011 video
on the internals of virtualenv.