How to get "python -m venv" to directly install latest pip version
I use upgrade-ensurepip
to update those pip
and setuptools
wheel files that are part of the ensurepip
package. It's not as elegant as being able to upgrade ensurepip
via pip
, but it's still preferable to doing it manually.
https://pypi.org/project/upgrade-ensurepip/
It is an expected behavior. python -m venv
calls python -m ensurepip
to install pip
and This answer shows that ensurepip
would only install the bundled version even with --upgrade
option. There isn't any official option to update the bundled pip
and setuptools
.
Well I have also no good idea to fix this problem as it just is the designed behavior. I would like to give two suggestions:
Use
pipenv
. It is really good! And it will be the next-generation official package manager in the future(Although there is a big problem related to current Pypi's structure. In short, a package manager can only decide the dependencies with downloading the whole package. This gives a huge difficulty to building dependencies graph.).Implement your custom
EnvBuilder
, actually there is an official example about this. And in the example, it also useget-pip.py
to install the latestpip
.
The trick is not to install the bundled version of pip (which will almost always be out of date), but to use it to install the most current version from the internet.
Standard library venv
offers a --without-pip
flag that can help here. After creating the virtual environment without pip, you can then you can "execute" ensurepip's wheel directly thanks to Python's zip importer. This is both faster and less hacky than installing pip and then immediately using that same pip installation to uninstall itself and upgrade.
Code speaks louder than words, so here's an example bash function for the process I've described:
# in ~/.bashrc or wherever
function ve() {
local py="python3"
if [ ! -d ./.venv ]; then
echo "creating venv..."
if ! $py -m venv .venv --prompt=$(basename $PWD) --without-pip; then
echo "ERROR: Problem creating venv" >&2
return 1
else
local whl=$($py -c "import pathlib, ensurepip; whl = list(pathlib.Path(ensurepip.__path__[0]).glob('_bundled/pip*.whl'))[0]; print(whl)")
echo "boostrapping pip using $whl"
.venv/bin/python $whl/pip install --upgrade pip setuptools wheel
source .venv/bin/activate
fi
else
source .venv/bin/activate
fi
}
If you prefer the older project virtualenv
, it also offers --no-pip
, --no-setuptools
, and --no-wheel
flags to achieve the same on Python 2.7.
Note: Python 3.9+ venv
has an --upgrade-deps
option to immediately upgrade the pip/setuptools versions after creating an environment, see https://bugs.python.org/issue34556 for more info about that. I don't use this option because it still goes through an unnecessary install/uninstall of the vendored versions, which is inferior to the method of creating an environment with the latest versions directly as shown above.