A recurring problem with virtual environments is that it’s possible for them to become “stale” due to changes made outside the virtual environment:
- the underlying Python runtime is removed or upgraded/downgraded to a different feature release
- the environment is copied or otherwise transferred (network drive, USB key) to a machine with a different operating system or CPU architecture
- the environment was set up for an external software component that is removed or upgraded/downgraded to a different feature release (e.g. CUDA, ROCm)
- the environment was set up for some other hardware that is no longer present (e.g. an nVidia GPU being replaced with an AMD GPU)
The concept below aims to help mitigate this problem for the first two examples, while leaving room for future extensions that address recording expectations regarding other external hardware and software dependencies.
It doesn’t attempt to specify what consumers should do with the information once it is available, it just aims to define a way for tools creating and manipulating virtual environments to record information regarding the assumptions those tools were making when installing packages.
The proposal also covers a couple of other problems that come up with virtual environments:
- attempting to manage a single virtual environment with multiple tools, leading to it getting into an unexpected state
- not having a record of what the expected state of a virtual environment actually is (the package level
RECORDfiles only record what is actually present, not what is expected to be present)
venv-info folder
The first part of the proposal is to standardise on venv-info as a new top level folder in virtual environments to hold information about the assumptions made when installing packages into that virtual environment.
The suggested name is derived from the venv stdlib module and the .dist-info suffix used on package installation metadata folders.
On its own, the folder serves as an unambiguous marker that a folder is a virtual environment (rather than something like a portable base Python runtime, such as those provided by python-build-standalone).
Custom metadata files
To avoid name clashes, all custom metadata files added to venv-info should be prefixed with the PyPI package name of the tool defining the custom metadata file (for example, venvstacks_layer.json).
Standardised metadata files
venv-info/MANAGER
Directly analogous to the INSTALLER file in dist-info directories, this file is for tools that manage virtual environments (like tox, nox, pdm, uv, pipx, poetry, venvstacks, etc) to record that the environment has been created by a specific tool.
This will allow for a better UX when someone does something like run uv lock in a project folder managed by pdm and vice-versa (at least in cases where the .venv/venv-info/MANAGER file already exists)
venv-info/pylock.toml
This internal lock file would record the list of packages that are expected to be present in the environment. Optionally, it may also record the provenance of those packages (by including the details of the wheels or source artifacts that were used to perform the package installation).
These lock files should NOT include any non-empty marker fields, as they’re a record of packages that are actually installed in the environment, not packages which might need to be installed under different circumstances.
venv-info/environment.json
This would be a JSON file, initially defined with a single top-level markers key. This subdictionary would hold a record of the environment markers that were in effect when the environment was set up. The extra, extras, and dependency_groups keys that are used for package selection at installation time are intentionally omitted.
For example:
{
"markers": {
"implementation_name": "cpython",
"implementation_version": "3.13.7"
"os_name": "posix",
"platform_machine": "x86_64",
"platform_python_implementation": "CPython",
"platform_release": "6.6.87.2-microsoft-standard-WSL2",
"platform_system": "Linux",
"platform_version": "#1 SMP PREEMPT_DYNAMIC Thu Jun 5 18:30:46 UTC 2025",
"python_full_version": "3.13.7",
"python_version": "3.13",
"sys_platform": "linux"
}
}
The top level “markers” key is used to allow us to potentially add more information to this file in the future. Possible additions include more hardware details, operating system details in platform specific formats (e.g. capturing the contents of /etc/os-release on Linux), or other elements used in wheel selection (such as the target macOS version, or the Linux libc compatibility target).
Out of scope
Capturing info for base runtime environments
The environment.json and pylock.toml files would potentially also be relevant for base Python runtime environments.
As Python runtimes across various platforms and use cases have all sorts of conflicting layouts with different rules regarding where data files that need to be modified at installation time are allowed to be stored, defining a location for such files is outside the scope of this potential PEP.
Checking this info on runtime startup
When CPython (or another runtime) detects that it is running in a virtual environment, it could potentially look for and read-in venv-info/environments.json. Alternatively, it could run that check lazily the first time it triggers ImportError (avoiding the performance hit on every startup, while still being able to report that modules might be missing due to an ABI mismatch).
Leaving this out is part of the “not attempting to specify what consumers should do with this information” scope management approach. There are a lot of UX improvements that could be made if the information is made available by virtual environment creation tools. Working out which ones should be made is a sufficiently complex discussion that it isn’t feasible to have it at the same time as standardising the exact information to be recorded (even though it’s useful to speculate on the possibilities when deciding what information should be made available).
While I’ve thought about this problem at various times for a while, actually drafting this pre-PEP was prompted by a recent discussion with @brettcannon, @pf_moore, @sirosen, and @glyph after Glyph pointed out that the wheel variants proposal makes it even easier to run into this environment inconsistency problem.