The Python site module participates in interpreter startup and configures installation-specific import paths. It adds site-packages directories to sys.path, processes .pth files, attempts to import sitecustomize and usercustomize, and helps configure history and completion in interactive sessions.
These actions explain why installed distributions become importable and why two executions of the same Python version may have different paths. They also create a sensitive startup surface: executable lines in .pth files run on every interpreter launch, while customization modules can execute arbitrary code before the application starts.
Automatic import during startup
Python normally imports site automatically. The -S option disables that step.
python -S -c "import sys; print(sys.path)"With -S, site-specific directories and helper builtins are not added. Since Python 3.14, virtual-environment values for sys.prefix and sys.exec_prefix are configured during path initialization and no longer depend on the site module.
Call site.main() explicitly
If Python started with -S, importing site does not automatically apply the normal modifications. Call site.main() to request them.
import site
site.main()Libraries should not do this. Changing sys.path at runtime is global and may surprise unrelated components. The application’s entry point should own that decision.
How site directories are built
The module combines heads such as sys.prefix and sys.exec_prefix with platform-specific tails. On Unix, a typical directory is lib/pythonX.Y/site-packages; on Windows, it is usually Lib/site-packages.
Free-threaded builds may include a t suffix, such as python3.13t. Do not build these paths manually. Use site functions or Python sysconfig.
Read global site-packages paths
getsitepackages() returns recognized global site directories.
import site
for path in site.getsitepackages():
print(path)Embedded or unusual installations may behave differently. Portable tools should handle empty or unavailable results and respect the active virtual environment.
Read the user site path
getusersitepackages() returns the user-specific package directory.
import site
print(site.getusersitepackages())
print(site.ENABLE_USER_SITE)A computed path does not prove that it was added to sys.path. Inspect ENABLE_USER_SITE.
Interpret ENABLE_USER_SITE
The flag has three meaningful states:
True: enabled and added to the search path.False: disabled by the user through-sorPYTHONNOUSERSITE.None: disabled for security reasons or by an administrator.
Do not collapse the value with bool() when you need to distinguish user preference from security policy.
Disable user packages
The -s option disables the user site:
python -s -c "import site; print(site.ENABLE_USER_SITE)"PYTHONNOUSERSITE provides similar behavior. Services, scheduled jobs, and reproducible environments often benefit from excluding personal packages.
USER_BASE and PYTHONUSERBASE
getuserbase() returns the base used by the user installation scheme. PYTHONUSERBASE can override the default.
import site
print(site.getuserbase())
print(site.USER_BASE)Changing this variable affects where installers place user scripts, modules, and data. Set it before Python starts and document it in build pipelines.
Use python -m site
The command-line interface prints sys.path, the user base, user site, and enablement state.
python -m site
python -m site --user-base
python -m site --user-siteWhen user-directory options are supplied, the exit code indicates whether the user site is enabled, disabled by the user, or blocked for security or administrative reasons.
Path configuration files
Files ending in .pth inside site directories are processed in alphabetical order. Ordinary lines add existing paths to sys.path. Blank lines and comments are ignored.
# example.pth
/opt/my_app/libs
/opt/my_app/pluginsNonexistent paths are skipped and duplicates are avoided. The module does not require an entry to be a directory; an existing file can also be added.
Alphabetical order affects imports
File names determine processing order, which can affect module precedence. If the same import name exists in two locations, the final sys.path order determines which one wins.
Avoid undocumented naming tricks such as 00-first.pth. Prefer clean virtual environments and ordinary package installation.
Executable lines in .pth files
A line beginning with import or import is executed on every interpreter startup.
import my_startup_hookThis happens even when the application never uses the related package. The one-line restriction is deliberate and discourages complex startup logic.
Security risk of .pth execution
Anyone able to write into a site-packages directory can potentially gain persistent code execution in every Python process using that environment. Protect permissions and treat .pth files as executable configuration.
from pathlib import Path
import site
for directory in site.getsitepackages():
for file in Path(directory).glob('*.pth'):
print(file)
for line in file.read_text(errors='replace').splitlines():
if line.startswith(('import ', 'import\t')):
print(' executes:', line).pth file encoding
Since Python 3.13, site first decodes .pth files as UTF-8 and falls back to the locale encoding. Use UTF-8 for predictability and avoid unnecessary non-ASCII characters in infrastructure paths.
Add a site directory programmatically
addsitedir() adds a directory and processes its .pth files.
import site
site.addsitedir('/opt/my_app/site-packages')This changes global import state and may execute startup lines. Never pass an untrusted path. Plugin systems should prefer controlled installation and process restarts.
sitecustomize
After path processing, Python tries to import sitecustomize. Administrators can use it for small global policies, audit hooks, encoding choices, or corporate startup configuration.
A missing module is silently ignored, but other exceptions can produce confusing startup failures. Keep the module small, tested, and independent of fragile external services.
usercustomize
When the user site is enabled, Python attempts to import usercustomize from the user site-packages directory.
It can customize trusted interactive sessions, but applications should not depend on it. Production services often disable user site to prevent personal preferences from altering behavior.
Avoid printing during startup
Output from customization modules may corrupt protocols, JSON-producing tools, and command-line programs. With pythonw.exe, output may be silently discarded.
Log only when explicitly enabled and send messages to an appropriate protected destination.
Automatic readline configuration
In interactive mode without -S, site configures rlcompleter and history when readline is available. The history file is commonly ~/.python_history.
For completion behavior and dynamic-attribute side effects, see Python rlcompleter.
Disable the interactive hook
sys.__interactivehook__ controls this setup. A customization module can remove it.
import sys
if hasattr(sys, '__interactivehook__'):
del sys.__interactivehook__Do this only when you own the interactive experience. A library should not modify the hook globally.
Virtual environments and pyvenv.cfg
pyvenv.cfg may contain include-system-site-packages = true. When false, the environment excludes global packages.
For reproducible projects, keep it false and install every dependency into the venv. Global packages can hide undeclared requirements.
Inspect virtual-environment prefixes
import sys
print('prefix:', sys.prefix)
print('base_prefix:', sys.base_prefix)
print('venv:', sys.prefix != sys.base_prefix)In Python 3.14, these values remain correct even with -S.
site or sysconfig?
Use site to inspect active directories, user-site status, and startup customization. Use sysconfig for structured installation and build schemes.
Do not infer cross-platform rules from one observed path on one machine.
Diagnose an unexpected import
import module
import sys
print(module.__file__)
print('\n'.join(sys.path))Then inspect .pth files, PYTHONPATH, user site, virtual-environment settings, and customization modules. Python pkgutil can list available modules.
PYTHONPATH interaction
PYTHONPATH influences startup search paths before several site operations. A global value can affect every Python environment.
Avoid setting it permanently system-wide. Prefer a controlled editable installation or virtual-environment configuration.
Isolated mode with -I
The -I option ignores PYTHON* environment variables and disables user site, among other protections.
python -I -c "import sys; print(sys.path)"It is useful for administrative tools that should be less influenced by a user’s environment, although installation-level customizations still need review.
Test sitecustomize safely
Use a temporary virtual environment, place the module in its site-packages directory, and launch a subprocess.
import subprocess
result = subprocess.run(
['.venv/bin/python', '-c', 'print("ok")'],
text=True,
capture_output=True,
check=True,
)
assert result.stdout.strip() == 'ok'Test normal startup, -S, -s, errors, and missing output streams. Never experiment in global Python.
Audit startup differences
python -m site
python -s -m site
python -S -c "import sys; print(sys.path)"
python -I -m siteThe differences reveal the effects of user site, the site module, and isolated mode.
Common mistakes
- Adding user-controlled paths with
addsitedir(). - Putting complex logic in a
.pthimport line. - Using
sitecustomizeas a plugin system. - Printing to stdout during startup.
- Depending on global packages inside a venv.
- Confusing an existing user-site directory with an enabled one.
- Building site-packages paths manually.
Best practices
- Use clean reproducible virtual environments.
- Protect site-packages permissions.
- Audit executable
.pthlines. - Keep customization modules minimal.
- Disable user site in services.
- Use sysconfig for structured paths.
- Test startup in subprocesses.
Conclusion
The Python site module explains much of automatic import configuration: site-packages directories, .pth files, user packages, and customization hooks.
This convenience runs before the application and demands strict control. Protect directories, avoid complex startup logic, and use virtual environments. Consult the official site documentation and the sys.path initialization documentation.







