【问题标题】:How to get "python -m venv" to directly install latest pip version如何让“python -m venv”直接安装最新的 pip 版本
【发布时间】:2019-01-14 04:44:04
【问题描述】:

作为新 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)

我在/opt/python 下有 25 个这样的版本,尽管我主要使用不是 EOL 的每个 major.minor 版本的五个最新版本。为了设置环境,我使用-p /opt/python/X.Y.Z/bin/python 选项运行virtualenvvirtualenvutils 以获得具有特定版本的虚拟环境。

对于 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.

我不太希望这会在 virtualenv 中得到解决,因为至少自 2014 年以来它就有一个 PendingDeprecationWarning(从 this question 的输出中可以看出)

在研究将virtualenvutils 中的python -m venv 替换为virtualenv 时,我首先手动创建了一个基于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)

那有一个旧的pip 版本!如果你使用它,你会得到:

您使用的是 10.0.1 版本的 pip,但可以使用 18.0 版本。
您应该考虑通过“pip install --upgrade pip”命令进行升级

在使用virtualenv 创建的虚拟环境中,您会立即获得最新版本:

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

我可以运行创建后步骤:

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

这需要额外的时间。如果pip 有一些安全更新,这将意味着运行非安全版本以获得安全版本,这是一个理想的攻击点。

virtualenvutils 开始,执行多个步骤来创建pip-less virtualenv 然后使用get-pip.py 添加pip 是微不足道的。从命令行来看,这不是那么简单:

$ /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

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

是什么导致/opt/python/3.7.0/bin/python -m venv 采用旧的pip 版本?那是3.7.0发布时可用的版本吗?

如何以某种方式更新我在/opt/python/3.7.0 下的安装,以便使用/opt/python/3.7.0/bin/python -m venv 创建具有最新pip 版本的virtualenv,而无需恢复为脚本、别名或使用多个命令?在/opt/python/3.7.0 下安装最新的pip 显然是不够的。

有两个捆绑的轮子:

/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

我怀疑我需要更新这些。有没有比手动更新更好的方法? /some/python -m venv 的一些选项会很好。

(并且运行 /some/python -m ensurepip --upgrade 并不能解决问题)


运行已弃用的/opt/python/3.7.0/bin/pyvenv 具有相同的旧pip 版本问题。

【问题讨论】:

  • 看起来bugs.python.org/issue30628 指的是这个问题,但错误站点目前已关闭。
  • 为了能够在没有警告的情况下继续进行,我最终创建了一个single file utility,它在_bundled 中下载新的.whl 文件并更新ensurepip/__init__.py。也可在PyPI 获得
  • 手动升级运行python -m pip install --upgrade pip setuptools wheel 不要只运行pip install,因为它会为你拥有的任何默认点创建一个shebang

标签: python pip virtualenv python-venv


【解决方案1】:

诀窍不是安装 pip 的捆绑版本(它几乎总是过时的),而是使用它来安装最新版本互联网。

标准库venv 提供了一个--without-pip 标志,可以在这里提供帮助。在没有 pip 的情况下创建虚拟环境后,您可以直接“执行”ensurepip 的轮子,这要归功于 Python 的 zip 导入器。这比安装 pip 然后立即使用相同的 pip 安装来卸载自身并升级更快,也更简单。

代码胜于雄辩,下面是我描述的过程的示例 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
}

如果您更喜欢较旧的项目 virtualenv,它还提供 --no-pip--no-setuptools--no-wheel 标志以在 Python 2.7 上实现相同功能。

注意: Python 3.9+ venv 有一个 --upgrade-deps 选项,可以在创建环境后立即升级 pip/setuptools 版本,有关详细信息,请参阅 https://bugs.python.org/issue34556。我不使用这个选项,因为它仍然需要对供应商版本进行不必要的安装/卸载,这不如如上所示直接使用最新版本创建环境的方法。

【讨论】:

  • 很有趣,几个月前我写过a ve tool,它做了类似的事情。我可能想要完善它,因为显然我不是唯一一个希望解决必须在所有虚拟环境中更新 pip 的不便的人。不过应该在 Python 3.9 出来之前做...
【解决方案2】:

我使用upgrade-ensurepip 来更新pipsetuptools 轮子文件,它们是ensurepip 包的一部分。它不如通过pip 升级ensurepip 优雅,但还是比手动升级更好。

https://pypi.org/project/upgrade-ensurepip/

【讨论】:

  • 我不喜欢用户弄乱捆绑的 pip 版本的想法(例如,它们可能由 root 拥有并从 OS 包管理器安装,如果你弄乱那些你会混淆你的操作系统文件)
  • 好点。我已经改用conda,现在不用处理这个问题了。
【解决方案3】:

这是一种预期的行为。 python -m venv 调用python -m ensurepip 来安装pipThis answer 表明ensurepip 只会安装捆绑版本,即使有--upgrade 选项。没有任何官方选项可以更新捆绑的 pipsetuptools

好吧,我也没有解决这个问题的好主意,因为它只是设计行为。我想提出两个建议:

  1. 使用pipenv。真的很好!并且会是未来的下一代官方包管理器(虽然目前Pypi的结构存在很大问题。总之,包管理器只能通过下载整个包来决定依赖关系。这给构建依赖关系图。)。

  2. 实现您的自定义EnvBuilder,实际上有一个official example 与此有关。并且在示例中,它还使用get-pip.py来安装最新的pip

【讨论】:

  • 感谢 envbuilder 链接,我会调查的。对于我的用例,pipenvvirtualenvutils 有相当多的重叠,但我仍然需要链接到/usr/local/bin 中的实际可执行文件。 pipenv 宣布使用 Pipfile 以及每个项目根目录中的另一个配置文件(以多余的 TOML 格式启动)的恐怖使得它在长期内相当无趣。
  • pipenv 不仅与virtualenvutils 重叠,而且是pipvirtualenv 的组合,这意味着它完全涵盖了这两个工具。此外,如果您决定使用pipenv,则不再需要requirements.txt :-) 实际上我选择pipenv 的最大原因是它可以真正管理依赖关系,而不仅仅是将它们列为pip freeze > requirements.txt做。比如你删除Pipfile中的一个顶级依赖,然后运行pipenv clean,它会自动删除所有未使用的子依赖。好吧,毕竟,这取决于个人意见:-)
  • virtualenvutils 不是virtualenv,它的作用远不止于此。因为我已经摆脱了需要requirements.txt(和setup.cfgMakefiletox.inisetup.pydistbuild.tox 等)的任何东西pipenv 放在那里只会再次使开发树变得混乱。所以pipenv对我来说)只是额外的工作,没有任何好处。每当我更改删除某些东西的依赖项时,我都会从头开始保存并重新安装一个实用程序及其 virtualenv(无论如何,使用的 Python 肯定会有一个新的微版本),以获得正确的依赖项(如果不能恢复则恢复)已解决)。
  • 猜猜我们有不同的使用场景。
  • 我认为pipenv should probably not be recommended these days。不过,扩展 EnvBuilder 看起来很有趣。
猜你喜欢
  • 2018-10-23
  • 1970-01-01
  • 2019-11-18
  • 2020-02-16
  • 2022-11-07
  • 2013-12-01
  • 2014-01-15
  • 1970-01-01
相关资源
最近更新 更多