How PDM Uses PEP 582 and Virtual Environments
PDM (Python Development Master) is a modern package and dependency
manager that offers flexible dependency isolation by supporting both
traditional virtual environments and the local
__pypackages__ directory defined by PEP 582. While
traditional tools mandate an active virtual environment, PDM allows
developers to choose between creating an isolated .venv
directory or installing packages directly inside the project root via
PEP 582 mechanics. This guide explains how PDM implements both
approaches, how it manages package resolution, and how to switch between
them based on your project's workflow requirements.
Virtual Environments in PDM
In modern releases, PDM uses virtual environments as its default isolation strategy. This choice ensures out-of-the-box compatibility with the broader Python ecosystem, including IDEs, linters, and CI/CD pipelines.
When you initialize a project with pdm init, PDM prompts
you to select a Python interpreter. By default, it automatically creates
a dedicated virtual environment inside a .venv folder in
your project root.
Key mechanics of PDM’s virtual environment implementation include:
- Automatic Creation and Detection: PDM creates the
.venvdirectory automatically and detects existing virtual environments (such as those created byvirtualenv,venv, or Conda). - Transparent Execution: You do not need to manually
run an activation script (such as
source .venv/bin/activate). Instead, runningpdm run <command>executes the command within the context of the project’s virtual environment. - Standards-Compliant Metadata: Dependencies are
tracked using the
pyproject.tomlfile following PEP 621 specifications, and exact dependency graphs are locked inpdm.lock.
PEP 582 Support in PDM
PEP 582 introduced the concept of Python local package directories,
aiming to provide Python with an experience similar to Node.js's
node_modules. Instead of creating a complete virtual
environment with separate Python binaries, dependencies are installed
directly into a folder named __pypackages__ located in the
project root.
Although the Python Steering Council officially rejected PEP 582, PDM still maintains full support for developers who prefer this lightweight, activation-free workflow.
How PDM Implements PEP 582
When configured to use PEP 582, PDM adjusts how it installs and resolves libraries:
- Directory Structure: Dependencies are organized by
Python version inside the project:
__pypackages__/ └── 3.11/ ├── bin/ ├── include/ └── lib/ - Interpreter Resolution: Since standard Python
interpreters do not natively read
__pypackages__without modifications, PDM intercepts the execution path. When usingpdm run, PDM injects the path to__pypackages__/<version>/libinto thePYTHONPATHenvironment variable. - Global Script Hook: PDM provides a setup command
(
pdm --pep582) that installs a customsitecustomize.pyfile into your global Python installation. This hook enables standard commands likepython script.pyto recognize__pypackages__without needing thepdm runprefix.
Configuring PDM: Virtual Environments vs. PEP 582
PDM lets you switch between virtual environments and PEP 582 at the global or project level.
Enabling Virtual Environments (Default)
To ensure PDM uses virtual environments for a project, configure the
python.use_venv setting:
pdm config python.use_venv trueWhen this setting is enabled, commands like pdm install
and pdm add place packages inside .venv.
Enabling PEP 582
To switch to the PEP 582 directory structure, disable the virtual environment setting:
pdm config python.use_venv falseOnce disabled, remove any existing .venv directory and
run pdm install. PDM will automatically construct the
__pypackages__ hierarchy and install all dependencies
there.
Choosing Between the Two Approaches
- Use Virtual Environments if: You rely heavily on external tools (such as PyCharm, VS Code, or Docker containers) that expect standard virtual environment structures, or if you collaborate with teams using diverse toolsets.
- Use PEP 582 if: You want a clean, activation-free environment, lower disk overhead, or a centralized project directory structure where all project dependencies live alongside your application code.