-
-
Notifications
You must be signed in to change notification settings - Fork 182
Virtualenvs created from links are broken #380
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Do you think this is a case of astral-sh/uv#8429 or are you suggesting we can fix this at build time? |
I expect a sys variable is resolved incorrectly during interpreter startup, causing the wrong home in
|
I need a little more exposition alongside these examples, I don't follow what you're demonstrating there. I would be surprised if this wasn't a sysconfig issue, but of course it'd be great to fix here if we can. |
As shown, pbs creates broken venv when the base interpreter is a symlink. This is a bug, since it should be able to do this, as system interpreter and pyenv succeed at this. The crash happens because This bug is the most likely candidate to crash the test suite in astral-sh/uv#8481 (comment). We need to figure out how |
Interestingly, after symlinking, some of the
|
That would definitely affect compilations of extension modules. |
Ohh interesting, it's because Python does:
|
I'm pretty sure I had to do something in PyOxidizer to work around this. Essentially mucking with the Python interpreter config to get it to resolve paths correctly because the default logic was insufficient. We should consider involving a CPython maintainer on this one as the behavior is a smell. ISTR Windows having special logic for path resolution because portable installs are a thing on Windows. But since most UNIX-like installs are to a fixed path, CPython doesn't support dynamic paths as well as we'd like. If CPython doesn't recognize the issue, we may have to patch our CPython build to handle dynamic install paths/symlibks correctly. This could be done with a custom site customize file. But since this included file can be disabled, we may need to patch C code. |
I haven't looked closely at this specific case, but we've definitely removed (Tangentially related, python/cpython#124825 is a proposal I filed to revisit adding lexical relative path resolution to |
I'm looking into this a bit. |
Ok, so for reference, the way prefix gets set in these builds is here. If the executable is at |
Ok... If you symlink an interpreter (but don't create a virtualenv), then So, above, it would still be Specifically, when you're not in a virtualenv, the However... if you create a virtualenv from a symlinked interpreter, then So we'd then fail to find |
I don't know if we should be setting |
One thing to note in the "symlink to Sorry, my own scratch notes... When I symlink
When I symlink
Ahhh, ok. The reason for this, I think, is that the When we launch from a virtualenv, we take whatever is in
The combination of these behaviors means that whatever we put in We can solve this in two ways:
(1) seems easier to me, though (2) might be the "better" fix? I'm just not confident on how we would implement it or how it would affect other, non-PBS Pythons. |
## Summary This PR improves our "don't fully resolve symlinks" behavior for `python-build-standalone` builds based on learnings from astral-sh/python-build-standalone#380 (comment). Specifically, we can now robustly detect whether a target executable will lead to a valid `prefix` or not, and iteratively resolve symlinks until we find a valid target executable. ## Test Plan ### Direct symlink to `python` Correctly resolves to the symlink target, rather than the symlink itself. ``` ❯ ln -s /Users/crmarsh/.local/share/uv/python/cpython-3.12.6-macos-aarch64-none/bin/python foo ❯ cargo run venv --python ./foo ❯ cat .venv/pyvenv.cfg home = /Users/crmarsh/.local/share/uv/python/cpython-3.12.6-macos-aarch64-none/bin implementation = CPython uv = 0.5.7 version_info = 3.12.6 include-system-site-packages = false prompt = uv ❯ .venv/bin/python -c "import sys" ``` ### Symlink to the Python installation Correctly does _not_ resolve the symlink. ``` ❯ ln -s /Users/crmarsh/.local/share/uv/python/cpython-3.12.6-macos-aarch64-none bar ❯ cargo run venv --python ./bar ❯ cat .venv/pyvenv.cfg home = /Users/crmarsh/workspace/uv/bar/bin implementation = CPython uv = 0.5.7 version_info = 3.12.6 include-system-site-packages = false prompt = uv ❯ .venv/bin/python -c "import sys" ``` ### Direct symlink to `python` in a symlinked Python installation Correctly resolves the direct symlink, but not the symlink of the Python installation. ``` ❯ ln -s bar/bin/python baz ❯ cargo run venv --python ./baz ❯ cat .venv/pyvenv.cfg home = /Users/crmarsh/workspace/uv/bar/bin implementation = CPython uv = 0.5.7 version_info = 3.12.6 include-system-site-packages = false prompt = uv ❯ .venv/bin/python -c "import sys" ```
@charliermarsh this one's biting us at work as well |
@gvwilson Can you explain a bit more about your setup? What are you using symlinked interpreters for? How are you creating your virtual environments? |
Hi @zanieb, I'll be replying for @gvwilson 😁 This issue appears to be presenting itself on Linux (Fedora) in an AppImage. The venv is being created with: Here is the configuration dump.... the
|
Are you managing your I'm having a bit of a hard time following what's going on. A complete reproduction with the commands you're using (and their output) would be really helpful. |
Those are being managed with I'll try and create a minimal repro and create a new issue in |
Here's a reproducer for $ docker run --rm -it ubuntu:24.10
# apt update && apt install -y curl git
# curl -LsSf https://astral.sh/uv/install.sh | sh
# source $HOME/.local/bin/env
# uv python install 3.12
# git clone https://github.com/scikit-hep/boost-histogram
# cd boost-histogram
# uvx cibuildwheel --only cp312-pyodide_wasm32
_ _ _ _ _ _ _
___|_| |_ _ _|_| |_| |_ _ _| |_ ___ ___| |
| _| | . | | | | | . | | | | | -_| -_| |
|___|_|___|___|_|_|___|_____|_|_|___|___|_|
cibuildwheel version 2.23.1
Build options:
platform: pyodide
allow_empty: False
architectures: wasm32
build_selector:
build_config: cp312-pyodide_wasm32
skip_config:
requires_python: >=3.8
enable: ['cpython-freethreading', 'cpython-prerelease', 'pypy']
output_dir: /boost-histogram/wheelhouse
package_dir: /boost-histogram
test_selector:
skip_config: cp*-musllinux_* cp313t-*win* pp311-*
before_all:
before_build:
before_test:
build_frontend:
*: build[uv]
cp312-pyodide_wasm32:
name: build
args: ['--exports', 'whole_archive']
build_verbosity: 0
config_settings:
container_engine: docker
dependency_constraints: pinned
environment:
PIP_ONLY_BINARY="numpy"
PIP_PREFER_BINARY="1"
manylinux_images: None
musllinux_images: None
repair_command:
test_command:
*: pytest -n auto --benchmark-disable {project}/tests
cp312-pyodide_wasm32: pytest --benchmark-disable {project}/tests
test_extras:
test_groups:
test
test_requires:
cloudpickle
hypothesis>=6.0
pytest-benchmark
pytest>=6.0
pytest-xdist
Cache folder: /root/.cache/cibuildwheel
Here we go!
Building cp312-pyodide_wasm32 wheel
CPython 3.12 Pyodide
Setting up build environment...
+ Download https://github.com/pypa/get-virtualenv/blob/20.29.3/public/virtualenv.pyz?raw=true to /root/.cache/cibuildwheel/virtualenv-20.29.3.pyz
+ /root/.cache/uv/archive-v0/m8zF1t0bWCOV1lDOploP5/bin/python -sS /root/.cache/cibuildwheel/virtualenv-20.29.3.pyz --activators= --no-periodic-update --pip=embed --no-setuptools --no-wheel --python /root/.cache/uv/archive-v0/m8zF1t0bWCOV1lDOploP5/bin/python /tmp/cibw-run-zmv0cabc/cp312-pyodide_wasm32/build/venv
created virtual environment CPython3.12.9.final.0-64 in 259ms
creator CPython3Posix(dest=/tmp/cibw-run-zmv0cabc/cp312-pyodide_wasm32/build/venv, clear=False, no_vcs_ignore=False, global=False)
seeder FromAppData(download=False, pip=embed, via=copy, app_data_dir=/root/.local/share/virtualenv)
added seed packages: pip==25.0.1
+ python -m pip install --upgrade pip -c /root/.cache/uv/archive-v0/m8zF1t0bWCOV1lDOploP5/lib/python3.12/site-packages/cibuildwheel/resources/constraints-pyodide312.txt
Could not find platform independent libraries <prefix>
Could not find platform dependent libraries <exec_prefix>
Python path configuration:
PYTHONHOME = (not set)
PYTHONPATH = (not set)
program name = '/tmp/cibw-run-zmv0cabc/cp312-pyodide_wasm32/build/venv/bin/python'
isolated = 0
environment = 1
user site = 1
safe_path = 0
import site = 1
is in build tree = 0
stdlib dir = '/install/lib/python3.12'
sys._base_executable = '/root/.local/share/uv/python/cpython-3.12.9-linux-x86_64-gnu/bin/python3.12'
sys.base_prefix = '/install'
sys.base_exec_prefix = '/install'
sys.platlibdir = 'lib'
sys.executable = '/tmp/cibw-run-zmv0cabc/cp312-pyodide_wasm32/build/venv/bin/python'
sys.prefix = '/install'
sys.exec_prefix = '/install'
sys.path = [
'/install/lib/python312.zip',
'/install/lib/python3.12',
'/install/lib/python3.12/lib-dynload',
]
Fatal Python error: init_fs_encoding: failed to get the Python codec of the filesystem encoding
Python runtime state: core initialized
ModuleNotFoundError: No module named 'encodings'
Current thread 0x00007f8c21d3c740 (most recent call first):
<no Python frame>
Traceback (most recent call last):
File "/root/.cache/uv/archive-v0/m8zF1t0bWCOV1lDOploP5/bin/cibuildwheel", line 12, in <module>
sys.exit(main())
^^^^^^
File "/root/.cache/uv/archive-v0/m8zF1t0bWCOV1lDOploP5/lib/python3.12/site-packages/cibuildwheel/__main__.py", line 49, in main
main_inner(global_options)
File "/root/.cache/uv/archive-v0/m8zF1t0bWCOV1lDOploP5/lib/python3.12/site-packages/cibuildwheel/__main__.py", line 184, in main_inner
build_in_directory(args)
File "/root/.cache/uv/archive-v0/m8zF1t0bWCOV1lDOploP5/lib/python3.12/site-packages/cibuildwheel/__main__.py", line 351, in build_in_directory
platform_module.build(options, tmp_path)
File "/root/.cache/uv/archive-v0/m8zF1t0bWCOV1lDOploP5/lib/python3.12/site-packages/cibuildwheel/pyodide.py", line 244, in build
env = setup_python(
^^^^^^^^^^^^^
File "/root/.cache/uv/archive-v0/m8zF1t0bWCOV1lDOploP5/lib/python3.12/site-packages/cibuildwheel/pyodide.py", line 131, in setup_python
call(
File "/root/.cache/uv/archive-v0/m8zF1t0bWCOV1lDOploP5/lib/python3.12/site-packages/cibuildwheel/util.py", line 154, in call
result = subprocess.run(
^^^^^^^^^^^^^^^
File "/root/.local/share/uv/python/cpython-3.12.9-linux-x86_64-gnu/lib/python3.12/subprocess.py", line 573, in run
raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '['/tmp/cibw-run-zmv0cabc/cp312-pyodide_wasm32/build/venv/bin/python', '-m', 'pip', 'install', '--upgrade', 'pip', '-c', '/root/.cache/uv/archive-v0/m8zF1t0bWCOV1lDOploP5/lib/python3.12/site-packages/cibuildwheel/resources/constraints-pyodide312.txt']' returned non-zero exit status 1. (also posted this on the linked uv issue) |
Weird hack to work around: astral-sh/python-build-standalone#380 If we resolve the symlink all the way, the python-host interpreter works but won't install into our pyodide venv. If we don't resolve the symlink, sys.prefix is calculated incorrectly. To ensure that we get the right sys.prefix, we explicitly set it with the PYTHONHOME environment variable and then call the symlink. [integration]
Weird hack to work around: astral-sh/python-build-standalone#380 If we resolve the symlink all the way, the python-host interpreter works but won't install into our pyodide venv. If we don't resolve the symlink, sys.prefix is calculated incorrectly. To ensure that we get the right sys.prefix, we explicitly set it with the PYTHONHOME environment variable and then call the symlink.
Weird hack to work around: astral-sh/python-build-standalone#380 If we resolve the symlink all the way, the python-host interpreter works but won't install into our pyodide venv. If we don't resolve the symlink, sys.prefix is calculated incorrectly. To ensure that we get the right sys.prefix, we explicitly set it with the PYTHONHOME environment variable and then call the symlink.
Unlike a system interpreter or a pyenv installation, pbs can't create venv from a symlink to the pbs installation location. PYTHONHOME is in the wrong location (that of the link, i think), which causes the encoding error.
I've only tested linux, i expect windows isn't affected (different venv mechanism, no symlinks by default), but i expect macos is affected, too.
The text was updated successfully, but these errors were encountered: