Skip to content
Open
Changes from 1 commit
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
ceeaa3b
initial file
rickeylev Jun 27, 2025
d0a9289
add some core content
rickeylev Jun 28, 2025
41d2ea8
rename to motivation
rickeylev Jun 28, 2025
65a415c
note it enables more advanced optimizations
rickeylev Jun 28, 2025
4175b20
add foot notes, relocatable term section, links
rickeylev Jun 29, 2025
bbc85b7
update discussion, sponsor headers to pending
rickeylev Jun 29, 2025
a0c2529
rst fixups
rickeylev Jun 29, 2025
8e6e21e
fixup italics
rickeylev Jun 29, 2025
37202ca
rename to relative-venv
rickeylev Jun 29, 2025
b81c50f
clarify advanced deployment options, reflow some text
rickeylev Jun 30, 2025
55a5e28
add specification, rationale section; doc why env vars arent an option
rickeylev Jun 30, 2025
e09b00d
also mention curdir syntax handling
rickeylev Jun 30, 2025
c7a6a9b
update some todo text
rickeylev Jun 30, 2025
bc1ffbd
update codeowners
rickeylev Jun 30, 2025
2301d2a
add initial discussion footnote link
rickeylev Jun 30, 2025
e14b01f
add fr footnote
rickeylev Jun 30, 2025
175f378
revert codeowners change
rickeylev Jun 30, 2025
31cb756
remove packaging-related specs
rickeylev Jul 2, 2025
cd46f4d
fix lint errors with headers
rickeylev Jul 2, 2025
b532f5c
set sponsor
rickeylev Jul 2, 2025
99434fc
set sponsor as codeowner
rickeylev Jul 2, 2025
862142a
clarify title to focus on core pyvenv.cfg home behavior
rickeylev Jul 2, 2025
1c8fb2d
fix typo; remove host-relocatable mention; remove non-germane copying…
rickeylev Jul 2, 2025
c542890
fix typos, grammar
rickeylev Jul 2, 2025
3240227
Apply suggestions from code review
rickeylev Jul 2, 2025
557cb71
fix up markdown and text width
rickeylev Jul 2, 2025
0579623
fix title underlines
rickeylev Jul 2, 2025
c9388b3
link to relative venv reference implementation
rickeylev Jul 2, 2025
b959f24
Apply suggestions from code review
rickeylev Jul 6, 2025
5b259cc
Apply suggestions from code review
rickeylev Aug 17, 2025
560dadb
Merge branch 'main' of https://github.com/python/peps into relative.v…
rickeylev Aug 17, 2025
f41ed51
Merge branch 'relative.venvs' of https://github.com/rickeylev/peps in…
rickeylev Aug 17, 2025
5cbc9f5
better answer why/how relvenvs help; wrap some long lines
rickeylev Aug 17, 2025
0af0eea
Apply AA-Turner suggestions
rickeylev Aug 21, 2025
68dd5e0
add refs, remove CWD acronym, fix grammar
rickeylev Aug 21, 2025
b50a80c
address review comments: better split and organize rationale/motivation
rickeylev Aug 24, 2025
af8f880
Merge branch 'main' into relative.venvs
AA-Turner Sep 29, 2025
ae5a67f
Apply markup and simple grammar fixes from code review
ncoghlan Oct 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
rst fixups
  • Loading branch information
rickeylev committed Jun 29, 2025
commit a0c2529c371faa91154279fc37f7593cb702938f
65 changes: 33 additions & 32 deletions peps/pep-0796.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ This PEP describes how a Python virtual environment can be configured
to allow copying it as-is to different hosts and still have a functioning
virtual environment. Making this work consists of two main pieces:

* Using a relative path for `home` in `pyvenv.cfg`, which Python canonicalizes
* Using a relative path for ``home`` in ``pyvenv.cfg``, which Python canonicalizes
at runtime.
* Having package installers recognize a host-relocatable venv and generate
appropriate outputs, e.g. script wrappers.
Expand All @@ -29,16 +29,16 @@ virtual environment. Making this work consists of two main pieces:
Motivation
==========

There are two main motivations for allowing relative paths in `pyvenv.cfg`
There are two main motivations for allowing relative paths in ``pyvenv.cfg``
and thus enabling host-relocatable virtual environments.

First, it is currently proscribed that the `home` value in `pyvenv.cfg` be an
First, it is currently proscribed that the ``home`` value in ``pyvenv.cfg`` be an
absolute path. The behavior of relative paths is unspecified.
While techniques exist to work around this for every other
sub-part of a virtual environment, the one remaining part without a teneable
solution is how the Python runtime itself finds `PYTHONHOME`. This is because,
currently, the startup process requires absolute paths be used for the `home`
key in `pyvenv.cfg`. If a relative path is used, behavior is unspecified
solution is how the Python runtime itself finds ``PYTHONHOME``. This is because,
currently, the startup process requires absolute paths be used for the ``home``
key in ``pyvenv.cfg``. If a relative path is used, behavior is unspecified
(currently, it is relative to the process's current working directory, making
it untenable to use).

Expand Down Expand Up @@ -77,38 +77,38 @@ Python Runtime Changes

The Python runtime itself *almost* already supports host-relocating virtual
environment and the only change needed is to define how it resolves relative
paths for `home` in `pyvenv.cfg`.
paths for ``home`` in ``pyvenv.cfg``.

Today, relative paths resolve relative to the process's current working
directory. Because CWD isn't knowable in advance, it makes relative paths today
effective impossible.

Instead, the paths should be relative to the location of the `pyvenv.cfg` file.
Instead, the paths should be relative to the location of the ``pyvenv.cfg`` file.
This file is chosen as the anchor point because the tool that creates the file
also has to know where the Python runtime is, so can easily calculate the
correct relative path. For tools that read the `pyvenv.cfg`, it is also easy
to simple join the directory name of where `pyvenv.cfg` was found with the
correct relative path. For tools that read the ``pyvenv.cfg``, it is also easy
to simple join the directory name of where ``pyvenv.cfg`` was found with the
path in the config file. When a person reads the config file, they can do
similar, which is a lower cognitive burden and helps avoids the question of
"relative to what?"

This change is only a couple of lines in the start up code. Specifically, when
parsing the `pyvenv.cfg` file and finding the `home` value, it just needs to
parsing the ``pyvenv.cfg`` file and finding the ``home`` value, it just needs to
be checked if it's already absolute. If not, then join to the directory name
of the `pyvenv.cfg` file. The code alredy knows the directory and has helpers
of the ``pyvenv.cfg`` file. The code alredy knows the directory and has helpers
already present for checking if a path is absolute and joining two paths.

A proof-of-concept of this is implemented in
[rickeylev/feat.relative.pyvenv.home](https://github.com/python/cpython/compare/main...rickeylev:cpython:feat.relative.pyvenv.home)
`rickeylev/feat.relative.pyvenv.home <https://github.com/python/cpython/compare/main...rickeylev:cpython:feat.relative.pyvenv.home>`__

Virtual Environment Tool Changes
================================

Virtual environment management tools should support a mechanism to generate
a `pyvenv.cfg` file with a `home` key that is a relative path to the relevant
a ``pyvenv.cfg`` file with a ``home`` key that is a relative path to the relevant
Python installation.

For the standard library's `venv` module, the flag `--relative` will be added
For the standard library's ``venv`` module, the flag ``--relative`` will be added
to trigger this behavior.

Package Installer Changes
Expand All @@ -118,8 +118,8 @@ Package installers must be aware of when a relative virtual environment has
been defined so they can avoid using absolute paths. The two main places
absolute paths occur today are:

1. `bin/` scripts, where shebangs are rewritten.
2. `site-packages` symlinks.
1. ``bin/`` scripts, where shebangs are rewritten.
2. ``site-packages`` symlinks.

Instead, they should create relative symlinks pointing to the actual
installation directory for packages.
Expand All @@ -129,7 +129,7 @@ Relocating a Venv to Another Host
=================================

Copying the venv to another host is simple: copy the venv directory itself, the
relative location `home` points to, and preserve the relative directory
relative location ``home`` points to, and preserve the relative directory
structures.

In practice, this typically means copying a parent directory of the virtual
Expand All @@ -139,16 +139,16 @@ the group of virtual environments to relocate.
Backwards Compatibility
=======================

Because relative paths for `home` aren't usable in practice, and their
Because relative paths for ``home`` aren't usable in practice, and their
behavior undocumented and unspecified, there shouldn't be any backward
compatibility concerns.


How to Teach This
=================

Teaching this should be simple: if you use a relative path in `pyvenv.cfg`,
then it's relative to the directory containing the `pyvenv.cfg` file. This
Teaching this should be simple: if you use a relative path in ``pyvenv.cfg``,
then it's relative to the directory containing the ``pyvenv.cfg`` file. This
is simple to explain and understand.


Expand All @@ -157,7 +157,7 @@ Reference Implementation

A reference implementation is available by using the combination of:

* Python runtime from [rickeylev/feat.relative.pyvenv.home](https://github.com/python/cpython/compare/main...rickeylev:cpython:feat.relative.pyvenv.home)
* Python runtime from `rickeylev/feat.relative.pyvenv.home <https://github.com/python/cpython/compare/main...rickeylev:cpython:feat.relative.pyvenv.home>`__
* rules_python with (todo: alterations to use cpython build as in-build
runtime)

Expand All @@ -169,14 +169,15 @@ todo: list any that are brought up and unresolved
Footnotes
=========

* [rules_python](https://github.com/bazel-contrib/rules_python): implements
* `rules_python <https://github.com/bazel-contrib/rules_python>`__: implements
host-relocatable virtual environments.
* [rules_py](https://github.com/aspect-build/rules_py): implements
* `rules_py <https://github.com/aspect-build/rules_py>`__: implements
host-relocatable virtual environments.
* [`uv venv
relocatable`](https://docs.astral.sh/uv/reference/cli/#uv-venv--relocatable):
* `uv venv
relocatable
<https://docs.astral.sh/uv/reference/cli/#uv-venv--relocatable>`__:
implements same-host relocatable virtual environments.
* [python-build-standalone](https://github.com/astral-sh/python-build-standalone):
* `python-build-standalone <https://github.com/astral-sh/python-build-standalone>`__:
A relocatable Python runtime.


Expand All @@ -186,17 +187,17 @@ Rejected Ideas
Relative to virtual env root
----------------------------

Having the `home` value in `pyvenv.cfg` relative to the virtual environments
Having the ``home`` value in ``pyvenv.cfg`` relative to the virtual environments
root directory would work just as well, but this idea is rejected because it
requires additional effort to compute the virtual env root.

Unspecified `home` means to dynamically compute home
Unspecified home means to dynamically compute home
----------------------------------------------------

Today, if a `pyvenv.cfg` file doesn't set `home`, the runtime will try to
Today, if a ``pyvenv.cfg`` file doesn't set ``home``, the runtime will try to
dynamically compute it by checking if the current executable (which is typicall
the venv's `bin/python3` symlink) is a symlink and, if so, use where that
points as `PYTHONHOME`.
the venv's ``bin/python3`` symlink) is a symlink and, if so, use where that
points as ``PYTHONHOME``.

This behavior is undesirable for a couple reasons:

Expand Down