Skip to content
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

Poetry tries using Python2 (usr/local/bin/python) instead of the provided distribution during install #6940

Open
4 tasks done
Taarek opened this issue Nov 2, 2022 · 10 comments
Labels
kind/bug Something isn't working as expected status/triage This issue needs to be triaged

Comments

@Taarek
Copy link

Taarek commented Nov 2, 2022

Issue

I don't have any reproducing steps, but I used to have Poetry 1.1-something, just earlier I uninstalled it to install 1.2.2.
I made sure to use python3.11 - after the curl command. But for whatever reason it still tries to use Python 2?

Whenever I try to run poetry update or poetry install it just fails with failed to query /usr/local/bin/python with code 2 err: 'No such file or directory' suddenly.

I tried searching for any existing issues, but searching for "No such file or directory" or "Wrong Python" or "Python 2" gives a ton of results, so apologies if this is a duplicate.

Edit: I did find this #6841 & #6371, but I tried what both the OP and the people replying suggested, and still get the same result.

Much later edit:
Doing poetry env use python3.10 then poetry install seems to work, so is this some weird Python 3.11 compatbility issue with Debian or something? (thinking about #6371) I did build Python 3.11 myself, don't remember if I did that with Python 3.10 as well.

@Taarek Taarek added kind/bug Something isn't working as expected status/triage This issue needs to be triaged labels Nov 2, 2022
@vfazio
Copy link
Contributor

vfazio commented Nov 2, 2022

So, the problem as i see it is that when poetry creates it's venv, the python executable within that venv is reporting the wrong sys._base_exectuable

This is with poetry 1.1.15 (we can't use 1.2.x for reasons)

3.11

python3 -c "import sys; print((sys._base_executable, sys.version))"
('/usr/local/bin/python3', '3.11.0 (main, Nov  2 2022, 16:46:02) [GCC 10.2.1 20210110]')

/opt/poetry/venv/bin/python3 -c "import sys; print((sys._base_executable, sys.version))"
('/usr/local/bin/python3', '3.11.0 (main, Nov  2 2022, 16:46:02) [GCC 10.2.1 20210110]')

/opt/poetry/venv/bin/python -c "import sys; print((sys._base_executable, sys.version))"
('/usr/local/bin/python', '3.11.0 (main, Nov  2 2022, 16:46:02) [GCC 10.2.1 20210110]')

3.10

python3 -c "import sys; print((sys._base_executable, sys.version))"  
('/usr/local/bin/python3', '3.10.5 (main, Jul  8 2022, 17:38:09) [GCC 10.2.1 20210110]')

/opt/poetry/venv/bin/python3 -c "import sys; print((sys._base_executable, sys.version))"
('/opt/poetry/venv/bin/python3', '3.10.5 (main, Jul  8 2022, 17:38:09) [GCC 10.2.1 20210110]')

/opt/poetry/venv/bin/python -c "import sys; print((sys._base_executable, sys.version))"
('/opt/poetry/venv/bin/python', '3.10.5 (main, Jul  8 2022, 17:38:09) [GCC 10.2.1 20210110]')

@vfazio
Copy link
Contributor

vfazio commented Nov 2, 2022

note that using virtualenv or venv don't seem to be problematic and the hashes of the python executables within all of the virtual environment directories all match up, which seems to imply it's some configuration/environment level issue.

@Taarek
Copy link
Author

Taarek commented Nov 3, 2022

Interesting, I ran something close to your command and got this:
Python 3.10:

poetry run python -c "import sys; print((sys._base_executable, sys.version))"
('/home/tarek/.cache/pypoetry/virtualenvs/{redacted}-_kCcl8pr-py3.10/bin/python', '3.10.4 (main, May  2 2022, 09:40:44) [GCC 10.2.1 20210110]')

Python 3.11:

poetry run python -c "import sys; print((sys._base_executable, sys.version))"
('/usr/local/bin/python3.11', '3.11.0 (main, Oct 25 2022, 10:13:14) [GCC 10.2.1 20210110]')

@vfazio
Copy link
Contributor

vfazio commented Nov 3, 2022

@Taarek my issue may be different, but i was hoping it was the same/similar. The fact that you get /usr/local/bin/python3.11 seems both good and bad. It obviously is not consistent with the 3.10 behavior but it's also not the problematic /usr/local/bin/python that I'm getting.

I don't want to snipe your issue and make it my own so i can spin up my own. Mine revolved around trying to make a venv for a project. Running poetry shell or poetry run actually fail when trying to create the in-project venv because it's looking for python and not python3

root@886a697372cb:/opt/tss# poetry run python3 -c "import sys; print((sys._base_executable, sys.version))"
Creating virtualenv tss in /opt/tss/.venv

  RuntimeError

  failed to query /usr/local/bin/python with code 2 err: 'No such file or directory'

  at /opt/poetry/venv/lib/python3.11/site-packages/virtualenv/discovery/cached_py_info.py:31 in from_exe
       27│     env = os.environ if env is None else env
       28│     result = _get_from_cache(cls, app_data, exe, env, ignore_cache=ignore_cache)
       29│     if isinstance(result, Exception):
       30│         if raise_on_error:
    →  31│             raise result
       32│         else:
       33│             logging.info("%s", result)
       34│         result = None
       35│     return result

In my case, it's almost like it's dropping the sys.exec_prefix and gluing the rest to sys.base_prefix due to the different results in my earlier post.

@vfazio
Copy link
Contributor

vfazio commented Nov 3, 2022

Ok... after making that last comment I actually found the following:

root@886a697372cb:/opt/tss# /opt/poetry/venv/bin/python -c "import sys; print((sys._base_executable, sys.version))"
('/usr/local/bin/python', '3.11.0 (main, Nov  2 2022, 16:46:02) [GCC 10.2.1 20210110]')

root@886a697372cb:/opt/tss# vi /opt/poetry/venv/pyvenv.cfg 
root@886a697372cb:/opt/tss# head /opt/poetry/venv/pyvenv.cfg
#home = /usr/local/bin
include-system-site-packages = false
version = 3.11.0
executable = /usr/local/bin/python3.11
command = /usr/local/bin/python3 -m venv --copies --clear /opt/poetry/venv

root@886a697372cb:/opt/tss# /opt/poetry/venv/bin/python -c "import sys; print((sys._base_executable, sys.version))"
('/opt/poetry/venv/bin/python', '3.11.0 (main, Nov  2 2022, 16:46:02) [GCC 10.2.1 20210110]')

So the home property seems to be driving the path replacement. This is problematic because poetry seems to always invoke python which causes the search for binary python vs the versioned one python3

oddly the behavior varies based on venv as using venv reports something more like what you're seeing

root@886a697372cb:/tmp/tmp.NRpQD8i4qu# python3 -m venv venv
root@886a697372cb:/tmp/tmp.NRpQD8i4qu# venv/bin/python -c "import sys; print((sys._base_executable, sys.version))"
('/usr/local/bin/python3.11', '3.11.0 (main, Nov  2 2022, 16:46:02) [GCC 10.2.1 20210110]')

So there may be a fundamental issue with Python 3.11 here

vfazio@vfazio2 /tmp/tmp.TMMouK27oi $ docker run -it python:3.10.8 bash
root@0ad1222a99d0:/# cd `mktemp -d`
root@0ad1222a99d0:/tmp/tmp.dCuquo5Mw2# python3 -m venv venv
root@0ad1222a99d0:/tmp/tmp.dCuquo5Mw2# venv/bin/python -c "import sys; print((sys._base_executable, sys.version))"
('/tmp/tmp.dCuquo5Mw2/venv/bin/python', '3.10.8 (main, Oct 26 2022, 03:28:14) [GCC 10.2.1 20210110]')
vfazio@vfazio2 /tmp/tmp.TMMouK27oi $ docker run -it python:3.11.0 bash
root@b177b69ae33f:/# cd `mktemp -d`
root@b177b69ae33f:/tmp/tmp.JpdXwm9GOx# python3 -m venv venv
root@b177b69ae33f:/tmp/tmp.JpdXwm9GOx# venv/bin/python -c "import sys; print((sys._base_executable, sys.version))"
('/usr/local/bin/python3.11', '3.11.0 (main, Oct 26 2022, 03:01:09) [GCC 10.2.1 20210110]')

though it is still suspect that the poetry venv is reporting a different version than standard venv

@vfazio
Copy link
Contributor

vfazio commented Nov 4, 2022

So, this may really be an issue with virtualenv + python3.11 and not necessarily poetry... but it's complex

This problem is likely related to:
https://bugs.python.org/issue46028
python/cpython#29041
python/cpython#30144

Variable 1:

as part of PR 29041

    for line in pyvenvcfg:
        key, had_equ, value = line.partition('=')
        if had_equ and key.strip().lower() == 'home':
            executable_dir = real_executable_dir = value.strip()
            base_executable = joinpath(executable_dir, basename(executable))
            break

The base executable is calculated based on the value of the home directory from pyvenv.cfg (which is why i saw the values change). This gets exposed via sys._base_executable. Note that this is a private field.

Variable 2:

When poetry runs commands, it does so as python and not as python3. When it's installed, the shebang for poetry is also pointing to python in the created venv.

Variable 3:

Poetry uses the system venv to install the virtual environment. This can be spied in the poetry pyvenv.cfg

command = /usr/local/bin/python3 -m venv --copies --clear /opt/poetry/venv

Note that it's not using symlinks and is explicitly using copies. This is important.

Variable 4:

Poetry uses virtualenv to setup subsequent virtualenvs. The virtualenv library references private sys._base_executable which may now point to an invalid binary given how the home config value affects resolution:

https://github.com/pypa/virtualenv/blob/20.16.6/src/virtualenv/discovery/py_info.py#L138

Result:

Because Poetry executes python out of the virtual environment, and because the virtualenv was not created with symlinks, and because 3.11 changed the calculation of sys._base_executable and because the virtualenv library references this private variable, we run into a situation where virtualenv dies because it tries to reference a binary that doesn't exist.

Using python3:

root@vfazio2:/tmp/tmp.U2ZVtBvloJ# /opt/poetry/venv/bin/python3 /opt/poetry/venv/lib/python3.11/site-packages/virtualenv/discovery/py_info.py | jq .system_executable
"/usr/local/bin/python3"

vs

root@vfazio2:/tmp/tmp.U2ZVtBvloJ# /opt/poetry/venv/bin/python /opt/poetry/venv/lib/python3.11/site-packages/virtualenv/discovery/py_info.py | jq .system_executable
"/usr/local/bin/python"

Removing poetry from the picture and creating a venv with --copies

root@vfazio2:/tmp/tmp.U2ZVtBvloJ# ls -la venv2/bin
total 84
drwxr-xr-x 2 root root  4096 Nov  4 15:20 .
drwxr-xr-x 5 root root  4096 Nov  4 15:19 ..
-rw-r--r-- 1 root root  9033 Nov  4 15:20 Activate.ps1
-rw-r--r-- 1 root root  1994 Nov  4 15:20 activate
-rw-r--r-- 1 root root   920 Nov  4 15:20 activate.csh
-rw-r--r-- 1 root root  2062 Nov  4 15:20 activate.fish
-rwxr-xr-x 1 root root   242 Nov  4 15:20 pip
-rwxr-xr-x 1 root root   242 Nov  4 15:20 pip3
-rwxr-xr-x 1 root root   242 Nov  4 15:20 pip3.10
-rwxr-xr-x 1 root root   242 Nov  4 15:20 pip3.11
-rwxr-xr-x 1 root root 11272 Nov  4 15:19 python
-rwxr-xr-x 1 root root 11272 Nov  4 15:19 python3
-rwxr-xr-x 1 root root 11272 Nov  4 15:19 python3.11

root@vfazio2:/tmp/tmp.U2ZVtBvloJ# venv2/bin/python /opt/poetry/venv/lib/python3.11/site-packages/virtualenv/discovery/py_info.py | jq .system_executable
"/usr/local/bin/python"
root@vfazio2:/tmp/tmp.U2ZVtBvloJ# venv2/bin/python3 /opt/poetry/venv/lib/python3.11/site-packages/virtualenv/discovery/py_info.py | jq .system_executable
"/usr/local/bin/python3"

Using a venv with symlinks instead of copies causes it to read through python to python3.11

root@vfazio2:/tmp/tmp.U2ZVtBvloJ# ls -la venv/bin
total 48
drwxr-xr-x 2 root root 4096 Nov  4 15:18 .
drwxr-xr-x 5 root root 4096 Nov  4 15:18 ..
-rw-r--r-- 1 root root 9033 Nov  4 15:18 Activate.ps1
-rw-r--r-- 1 root root 1991 Nov  4 15:18 activate
-rw-r--r-- 1 root root  917 Nov  4 15:18 activate.csh
-rw-r--r-- 1 root root 2059 Nov  4 15:18 activate.fish
-rwxr-xr-x 1 root root  241 Nov  4 15:18 pip
-rwxr-xr-x 1 root root  241 Nov  4 15:18 pip3
-rwxr-xr-x 1 root root  241 Nov  4 15:18 pip3.10
-rwxr-xr-x 1 root root  241 Nov  4 15:18 pip3.11
lrwxrwxrwx 1 root root    7 Nov  4 15:18 python -> python3
lrwxrwxrwx 1 root root   22 Nov  4 15:18 python3 -> /usr/local/bin/python3
lrwxrwxrwx 1 root root    7 Nov  4 15:18 python3.11 -> python3


root@vfazio2:/tmp/tmp.U2ZVtBvloJ# venv/bin/python3 /opt/poetry/venv/lib/python3.11/site-packages/virtualenv/discovery/py_info.py | jq .system_executable
"/usr/local/bin/python3.11"
root@vfazio2:/tmp/tmp.U2ZVtBvloJ# venv/bin/python /opt/poetry/venv/lib/python3.11/site-packages/virtualenv/discovery/py_info.py | jq .system_executable
"/usr/local/bin/python3.11"

there could be an argument made, i suppose, that virtualenv should maybe validate the system executable exists prior to setting it as "the answer"

Like I said, part of the problem is likely that poetry is always running "python" vs "python3" but the series of hoops to get here is complex.

@mousedownmike
Copy link

I'm new to poetry and this may be stating the obvious but I experienced this problem after updating to Ubuntu 22.04 LTS from 20.04. The only way I could work around this was to remove .cache/pypoetry/virtualenvs.

@neersighted
Copy link
Member

In your case, it was because Ubuntu 22.04 ships with a different Python version from Ubuntu 20.04, and the symlink to the interpreter was busted. Beware of #6371 on Ubuntu 22.04 (you may need a deadsnakes or pyenv Python because of this Ubuntu bug).

@vfazio
Copy link
Contributor

vfazio commented Nov 13, 2022

I'm hoping this is resolved with virtualenv 20.16.7 which was just cut and should be pulled into new installs, including 1.1.15. Upstream python also accepted a fix into mainline and backported it to 3.11 that will try to fallback to a versioned binary if an unversioned one is referenced but not available in the path pointed to by home in pyvenv.cfg

@FeepingCreature
Copy link

Sidenote: If Google brought you here, sudo apt install python-is-python3 (making python3 the default) will fix this on Ubuntu.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/bug Something isn't working as expected status/triage This issue needs to be triaged
Projects
None yet
Development

No branches or pull requests

5 participants