-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
ensurepip
error during Poetry venv creation when using outdated Python versions
#1697
Labels
Comments
edmorley
changed the title
Nov 12, 2024
ensurepip
error during venv creation when using outdated Python versionsensurepip
error during Poetry venv creation when using outdated Python versions
edmorley
added a commit
that referenced
this issue
Nov 12, 2024
When `python -m venv` is run, after creating the virtual environment it invokes `ensurepip` to install pip. The `ensurepip` module in older Python versions didn't correctly run its Python subprocesses in isolated mode, meaning that the working directory is added to `sys.path`. This can cause issues if the app's build directory contains files/directories that shadow expected package names (such as a `brotli` directory). For example: ``` -----> Installing Poetry 1.8.4 Error: Command '['/tmp/codon/tmp/cache/.heroku/python-poetry/venv/bin/python', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1. ! Internal Error: Unable to create virtual environment for Poetry. ! ! The 'python -m venv' command to create a virtual environment did ! not exit successfully. ! ! See the log output above for more information. ``` The best fix is for apps to upgrade to newer Python patch versions (3.8.14+, 3.9.14+, 3.10.6+), since they include the upstream `ensurepip` fix as well as many other bug and security fixes. However, to ensure venv creation still works on these older Python versions, as a workaround we can run the `python -m venv` command from a different working directory (as an alternative to isolated mode). Fixes #1697. GUS-W-17215816.
edmorley
added a commit
that referenced
this issue
Nov 12, 2024
When `python -m venv` is run, after creating the virtual environment it invokes `ensurepip` to install pip. The `ensurepip` module in older Python versions didn't correctly run its Python subprocesses in isolated mode, meaning that the working directory is added to `sys.path`. This can cause issues if the app's build directory contains files/directories that shadow expected package names (such as a `brotli` directory). For example: ``` -----> Installing Poetry 1.8.4 Error: Command '['/tmp/codon/tmp/cache/.heroku/python-poetry/venv/bin/python', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1. ! Internal Error: Unable to create virtual environment for Poetry. ! ! The 'python -m venv' command to create a virtual environment did ! not exit successfully. ! ! See the log output above for more information. ``` The best fix is for apps to upgrade to newer Python patch versions (3.8.14+, 3.9.14+, 3.10.6+), since they include the upstream `ensurepip` fix as well as many other bug and security fixes. However, to ensure venv creation still works on these older Python versions, as a workaround we can run the `python -m venv` command from a different working directory (as an alternative to isolated mode). Fixes #1697. GUS-W-17215816.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Looking at the buildpack metrics, I found a handful of failing builds from a single app, where the Poetry venv install was failing with:
In theory this should never fail, since the
python -m venv
command creates a virtual environment (including installing pip) using the wheels bundled in the Python stdlib, so doesn't have to fetch any remote resources - so in general should not be fallible unless there was a disk I/O error or similar.Unfortunately, the
venv
module doesn't surface the underlying error message which made this hard to debug, particularly since I initially couldn't get it to reproduce either on another app or locally.After a fair amount of trial and error, I managed to track this down to an intersection of the following:
ensurepip
module where it didn't correctly enable isolated mode (-I
) for the child Python process: ensurepip bootstrap breaks out of isolated environment python/cpython#90355. Which means the current working directory is added tosys.path
whenensurepip
is invoked duringvenv
creation.__init__.py
as a namespace package, rather than ignoring the directory: https://peps.python.org/pep-0420/brotli
in the build directory (example). (Even though they don't add it toPATH
or otherwise use it directly.)brotli
package, one of its vendored dependencies (urllib3
) uses it in an optional feature, and prior to pip 22.1 thebrotli
import wasn't correctly patched out/replaced during vendoring: Disable brotli import in urllib3 pypa/pip#10993. This meant pip would try and importbrotli
fromsys.path
when it was run (compared to all of the other imports, which are imported from pip's vendor directory). And whilst theurllib3
implementation gracefully handlesbrotli
not being installed (since it was an optional feature), if it finds the module, then it (quite reasonably) presumes it has the expected API.When all of the above conditions are combined, the result is that
ensurepip
will fail with anAttributeError: module 'brotli' has no attribute 'error'
exception (which sadly isn't shown in the logs, due to thevenv
command eating the output of theensurepip
subprocess).This can be reproduced without the buildpack in question by creating a directory named
brotli
in the app source (with any file within it, so Git is able to commit it). The app needs to be using one of the old Python versions listed above, and using Poetry as the package manager (which currently is the only package manager for which we invokevenv
, but in the future we'll be usingvenv
in other places too).The best way for apps to avoid this issue is to update to a newer patch release of their Python version. Not only will this include a fix for the
ensurepip
bug, but also several other security vulnerabilities. We do emit warnings already for these out of date patch versions, but unfortunately some users ignore them.From the buildpack side, our options are:
venv
/ Poetry, or entirely).brotli
directory.python -m venv
command from a different working directory (eg/tmp
), so it's not affected by the contents of the build directory even when isolation mode is not correctly enabled.I'm inclined to go with (3) given it's a small easy to maintain workaround, that won't require users to change Python patch version (as much as they really should just update for security reasons).
The text was updated successfully, but these errors were encountered: