简体   繁体   English

如何让“python -m venv”直接安装最新的pip版本

[英]How to get "python -m venv" to directly install latest pip version

As part of the compilation step for a new python version, I fetch and run get-pip.py , to have the latest pip installed next to the python executable:作为新 python 版本编译步骤的一部分,我获取并运行get-pip.py ,以便在 python 可执行文件旁边安装最新的 pip:

$ /opt/python/3.7.0/bin/python --version
Python 3.7.0
$ /opt/python/3.7.0/bin/pip --version
pip 18.0 from /opt/python/3.7.0/lib/python3.7/site-packages/pip (python 3.7)

I have 25 such versions under /opt/python , although I mostly use the five latest versions of each major.minor version that is not EOL.我在/opt/python下有 25 个这样的版本,尽管我主要使用不是 EOL 的每个 Major.minor 版本的五个最新版本。 To setup an invironment I used to run virtualenv or my virtualenvutils with the -p /opt/python/XYZ/bin/python option to get a virtual environment with a specific version.为了设置环境,我曾经使用-p /opt/python/XYZ/bin/python选项运行virtualenv或我的virtualenvutils以获得具有特定版本的虚拟环境。

With Python 3.7 this gives the imp module deprecation warning:在 Python 3.7 中,这会给出 imp 模块弃用警告:

$ virtualenv -p /opt/python/3.7.0/bin/python /tmp/py37virtualenv
Running virtualenv with interpreter /opt/python/3.7.0/bin/python
Using base prefix '/opt/python/3.7.0'
/opt/util/virtualenvutils/lib/python3.6/site-packages/virtualenv.py:1041: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
  import imp
New python executable in /tmp/py37virtualenv/bin/python
Installing setuptools, pip, wheel...done.

I have little hope this will be solved in virtualenv, as this has had a PendingDeprecationWarning at least since 2014 (as can be seen from the output in this question )我几乎不希望这会在 virtualenv 中得到解决,因为至少从 2014 年开始就有PendingDeprecationWarning (从这个问题的输出中可以看出)

While investigating replacing virtualenv with python -m venv in virtualenvutils , I first created a new venv based virtual environment by hand:在调查替换virtualenvpython -m venvvirtualenvutils ,我首先创建一个新的venv用手基于虚拟环境:

$ /opt/python/3.7.0/bin/python -m venv /tmp/py37venv
$ /tmp/py37venv/bin/pip --version
pip 10.0.1 from /tmp/py37venv/lib/python3.7/site-packages/pip (python 3.7)

That has an old pip version!那有一个旧的pip版本! If you use it, you'll get:如果你使用它,你会得到:

You are using pip version 10.0.1, however version 18.0 is available.您使用的是 pip 版本 10.0.1,但是版本 18.0 可用。
You should consider upgrading via the 'pip install --upgrade pip' command您应该考虑通过“pip install --upgrade pip”命令升级

In the virtual environment created with virtualenv you immediately get the latest version:在使用virtualenv创建的虚拟环境中,您会立即获得最新版本:

$ /tmp/py37virtualenv/bin/pip --version
pip 18.0 from /tmp/py37virtualenv/lib/python3.7/site-packages/pip (python 3.7)

I can run a post-creation step:我可以运行创建后步骤:

/tmp/py37venv/bin/pip install -U --disable-pip-version-check pip 

which will take extra time.这将需要额外的时间。 And if there was a some security update for pip , this would imply running the non-secure version to get a secure version, an ideal point of attack.如果pip有一些安全更新,这意味着运行非安全版本以获得安全版本,这是一个理想的攻击点。

From virtualenvutils it is trivial to do the multiple steps to create a pip -less virtualenv and then add pip using get-pip.py .virtualenvutils执行多个步骤来创建pip -less virtualenv 然后使用get-pip.py添加pip get-pip.py From the command-line this is not so simple:从命令行这不是那么简单:

$ /opt/python/3.7.0/bin/python -m venv --without-pip /tmp/py37venvnopip
$ /tmp/py37venvnopip/bin/python -c "from  urllib.request import urlopen; response = urlopen('https://bootstrap.pypa.io/get-pip'); open('/tmp/tmp_get_pip.py', 'w').write(response.read())"
$ /opt/python/3.7.0/bin/python /tmp/tmp_get_pip.py
......
$ /opt/python/3.7.0/bin/pip --version

pip 18.0 from /opt/python/3.7.0/lib/python3.7/site-packages/pip (python 3.7)来自 /opt/python/3.7.0/lib/python3.7/site-packages/pip (python 3.7) 的 pip 18.0

What is causing /opt/python/3.7.0/bin/python -m venv to take that old pip version?是什么导致/opt/python/3.7.0/bin/python -m venv采用旧的pip版本? Is that the version available when 3.7.0 was released? 3.7.0 发布时那个版本可用吗?

How can I update my install under /opt/python/3.7.0 in some way so that using /opt/python/3.7.0/bin/python -m venv creates a virtualenv with the latest pip version without reverting to scripts, aliases or using multiple commands?如何以某种方式更新我在/opt/python/3.7.0下的安装,以便使用/opt/python/3.7.0/bin/python -m venv创建一个具有最新pip版本的 virtualenv,而无需恢复到脚本、别名或使用多个命令? Having the latest pip installed under /opt/python/3.7.0 obviously is not enough./opt/python/3.7.0下安装最新的pip显然是不够的。

There are two bundled wheels:有两个捆绑的轮子:

/opt/python/3.7.0/lib/python3.7/ensurepip/_bundled/setuptools-39.0.1-py2.py3-none-any.whl
/opt/python/3.7.0/lib/python3.7/ensurepip/_bundled/pip-10.0.1-py2.py3-none-any.whl

I suspect I need to update those.我怀疑我需要更新这些。 Is there a better way than updating those by hand?有没有比手动更新更好的方法? Some option for /some/python -m venv would be nice. /some/python -m venv一些选项会很好。

(And running /some/python -m ensurepip --upgrade doesn't do the trick) (并且运行/some/python -m ensurepip --upgrade不起作用)


Running the deprecated /opt/python/3.7.0/bin/pyvenv has the same old pip version problem.运行已弃用的/opt/python/3.7.0/bin/pyvenv具有相同的旧pip版本问题。

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.诀窍不是安装pip 的捆绑版本(它几乎总是过时的),而是使用它来安装来自 Internet 的最新版本。

Standard library venv offers a --without-pip flag that can help here.标准库venv提供了一个--without-pip标志,可以在这里提供帮助。 After creating the virtual environment without pip, you can then you can "execute" ensurepip's wheel directly thanks to Python's zip importer.创建没有 pip 的虚拟环境后,您可以直接“执行”ensurepip 的轮子,这要归功于 Python 的 zip 导入器。 This is both faster and less hacky than installing pip and then immediately using that same pip installation to uninstall itself and upgrade.这比安装 pip 然后立即使用相同的 pip 安装卸载自身并升级更快,也更简单。

Code speaks louder than words, so here's an example bash function for the process I've described:代码胜于雄辩,所以这里是我描述的过程的示例 bash 函数:

# 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.如果您更喜欢旧项目virtualenv ,它还提供--no-pip--no-setuptools--no-wheel标志以在 Python 2.7 上实现相同的目标。

Python 3.9's venv may get an --upgrade-deps option to automate this, see https://bugs.python.org/issue34556 for more info about that. Python 3.9 的venv可能会获得一个venv --upgrade-deps选项来自动执行此操作,有关更多信息,请参阅https://bugs.python.org/issue34556

I use upgrade-ensurepip to update those pip and setuptools wheel files that are part of the ensurepip package.我使用upgrade-ensurepip来更新作为ensurepip包一部分的那些pipsetuptools轮文件。 It's not as elegant as being able to upgrade ensurepip via pip , but it's still preferable to doing it manually.它不像能够通过pip升级ensurepip那样优雅,但它仍然比手动升级ensurepip可取。

https://pypi.org/project/upgrade-ensurepip/ 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. python -m venv调用python -m ensurepip来安装pip并且这个答案表明即使使用--upgrade选项, ensurepip也只会安装捆绑版本。 There isn't any official option to update the bundled pip and setuptools .没有任何官方选项来更新捆绑的pipsetuptools

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:我想给出两个建议:

  1. Use pipenv .使用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.).并且未来会是下一代官方的包管理器(虽然目前Pypi的结构有很大的问题。总之,包管理器只能通过下载整个包来决定依赖。这给了一个巨大的难度构建依赖关系图。)。

  2. Implement your custom EnvBuilder , actually there is an official example about this.实现您的自定义EnvBuilder ,实际上有一个关于此的官方示例 And in the example, it also use get-pip.py to install the latest pip .在示例中,它还使用get-pip.py来安装最新的pip

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM