PEP 838 – Adding python-version to pyvenv.cfg
- Author:
- Konstantin Schütze <konstin at mailbox.org>
- Sponsor:
- Alex Waygood <alex.waygood at gmail.com>
- PEP-Delegate:
- Paul Moore <p.f.moore at gmail.com>
- Discussions-To:
- Pending
- Status:
- Draft
- Type:
- Standards Track
- Topic:
- Packaging
- Created:
- 15-Jul-2026
- Python-Version:
- 3.16
- Post-History:
- Pending
Abstract
This PEP proposes adding a python-version field to pyvenv.cfg
which records the Python interpreter used by a virtual environment.
It records only the major and minor version to be resilient to patch
version updates.
Motivation
pyvenv.cfg, as defined by PEP 405, only specifies the home
and include-system-site-packages keys. Different tools record different
information about the Python version of a virtual environment. For a virtual
environment created with Python 3.14.4 final:
- CPython’s
venvmodule adds aversionfield as'%d.%d.%d' % sys.version_info[:3](CPython source). Example:version = 3.14.4. - The
virtualenvpackage addsversion_infoandversionfields as".".join(str(i) for i in sys.version_info)and".".join(str(i) for i in sys.version_info[:3])(virtualenv source). Example:version_info = 3.14.4.final.0andversion = 3.14.4. - uv adds a
version_infofield based onplatform.python_version()(uv source). Example:version_info = 3.14.4.
This information is used by a variety of tools, see Appendix: Existing Tool Behavior. Some of them want to present the full Python version to the user for identification, while others only need the major and minor version of Python.
One problem is the different definitions of version and
version_info, and the lack of guarantees for downstream tools. There is
no guarantee that either field is present, nor is either field’s granularity
defined.
Another problem is that the Python interpreter underneath the virtual
environment may change. Linux distributions routinely update CPython patch
versions as part of regular updates within a single distribution version. uv
supports upgrading existing Python installations,
upgrading virtual environments using the interpreter in the process. A
version_info key in pyvenv.cfg with a patch version and a potential
prerelease component goes stale this way.
Tools interacting with virtual environments can fail after a Python patch-version upgrade when their assumptions about version granularity are violated. A standardized field with only major and minor version avoids this problem.
Specification
A new python-version field is added to pyvenv.cfg. It contains a
string value with the major and minor version of the Python interpreter, such
as 3.16. The value can be obtained with
f"{sys.version_info[0]}.{sys.version_info[1]}". Tools creating virtual
environments MUST write python-version to pyvenv.cfg. Reading
version or version_info is discouraged.
A Python interpreter MAY refuse to run from a virtual environment with a
mismatching python-version.
Rationale
The python-version key is not yet used by any known tool (GitHub code
search),
avoiding breakage in tools that read any of the existing keys. By
specifying only the major and minor version, the value remains fresh even if
the underlying Python interpreter is updated from one patch release to
another.
This PEP does not handle the case of python-version going stale due to
the underlying Python interpreter being updated to another minor version.
This may happen when upgrading from one Linux distribution version to another.
Such an update breaks any packages using CPython’s unstable C API and cannot
be fixed through a different way of recording values in pyvenv.cfg; it can
only be fixed by regenerating the virtual environment, resolving with the new
Python version and installing the appropriate packages. By performing a check
during interpreter startup, we avoid inscrutable errors at import time or at
runtime, and can inform the user about the problem.
To show accurate Python version information to the user, tools can present the
value of python-version, or if they need the full Python version, they can
query the interpreter for sys.version_info, invalidating this information
when the virtual environment interpreter or the underlying base executable
change. This PEP does not require any specific tool behavior, nor does it
disallow existing patterns. Its goal is to provide the required information
for correct, resilient implementations.
Backwards Compatibility
If python-version is not available, tools can fall back to the
existing unspecified fields or inspect the Python interpreter. There is no
known existing usage of python-version in pyvenv.cfg.
How to Teach This
A new specification page for pyvenv.cfg will be added to the Python
Packaging User Guide, including
documentation for this field. The field is not user-facing.
Reference Implementation
Reference implementations will be provided for uv, virtualenv, and CPython.
Appendix: Existing Tool Behavior
A non-exhaustive list of how tools parse version values:
- ty splits the dotted value and parses only the major and minor components, ignoring any remaining components (ty source). Ty only needs the major and minor version of Python.
- The VS Code Python extension parses both fields and
separately handles virtualenv-style values such as
3.9.0.final.0. When both fields are present, it selects the most specific version (VS Code source). VS Code presents the full Python version to the user for identification. - Microsoft Python Environment Tools requires at least three numeric
components for both fields, then parses the first two components
(Python Environment Tools source).
Its uv-specific parser stores only
version_info(Python Environment Tools uv source). VS Code presents the full Python version to the user for identification. - pre-commit compares
version_infowith thesys.version_infocomponents joined by dots. (pre-commit source, health-check source). This caused a failure where uv and pre-commit disagreed about virtual environment freshness checks. - Jute reads
version_info(Jute source). Jute presents the full Python version to the user for identification. - MediaHarbor parses the first two components of
version(MediaHarbor source). - Jac parses the first two components of
version(Jac source).
Copyright
This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive.