Description
Bug report
Bug description:
Previously, it was possible to have a functional (enough) venv by simply doing two things:
- Creating an empty pyvenv.cfg file
- Creating a bin/python3 which symlinked to the actual interpreter
The net effect was you had a sufficiently relocatable venv (at the interpreter level) to make it into a fully relocatable venv (at the application level). This is because Python would follow the symlink to locate its home, which let it get through initial bootstrapping, enough to pick a venv-relative site-packages directory.
The net effect was Python followed the symlink to find home, which let it bootstrap itself enough to find the venv's site-packages. Once at that point, application code is able to hook in and do some fixups.
This bug seems to be introduced by #126987
I'm still looking at the changes to figure out why, exactly. I'm pretty confident it's that PR, though -- in my reproducer, things work before it, but break after it.
This behavior of automatically find Python home is something Bazel's rules_python has come to rely on. Insofar as venvs are concerned, the two particular constraints Bazel imposes are:
- Absolute paths can't be used. This is because they may be machine specific. In Bazel, the machine that generates pyvenv.cfg may be different than who uses it at runtime (e.g a remote build worker generates it, and a user runs it locally).
- The file system must be assumed to be read-only after building. This prevents creating/modifying a pyvenv.cfg at runtime in the venv's directory to work around (1).
(As an aside, how the env var PYTHONEXECUTABLE
gets handled might have also been affected by this; I haven't looked deeply yet, but one of my tricks was to set that to the venv bin/python3 path and invoke the real interpreter, but that seems to no longer work, either)
I'll post a more self contained reproducer in a bit. In the meantime, something like this can demonstrate the issue:
mkdir myvenv
cd myvenv
touch pyvenv.cfg
mkdir bin
ln -s <path to python> bin/python3
mkdir -p lib/python3.14/site-packages
bin/python3 -c 'import sys; print(sys.prefix); print(sys.base_prefix); print(sys.path)'
After the change, it'll print warnings and e.g. /usr/local as the prefixes, which is incorrect. sys.path won't have the venv's site-packages directory, which is incorrect.
Before the change, it'll print the venv directory, underlying interpreter directory, and the venv's site-packages, which is correct.
cc @FFY00 (author of above PR)
CPython versions tested on:
3.14
Operating systems tested on:
Linux