升级`pip`会删除其他python的pip [英] Upgrading `pip` removes other python's pips

查看:41
本文介绍了升级`pip`会删除其他python的pip的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在CentOS 7系统上,我安装了多个版本的Python,每个版本都有自己的 pip 版本:

On a CentOS 7 system, I have multiple versions of Python installed, each with their own version of pip:

# head -n1 /usr/local/bin/pip3.*
==> /usr/local/bin/pip3.6 <==
#!/usr/bin/python3

==> /usr/local/bin/pip3.7 <==
#!/usr/local/bin/python3.7

==> /usr/local/bin/pip3.8 <==
#!/usr/local/bin/python3.8

当我要求 pip3.8 进行自我升级时,它会删除已安装的 pip3.7 :

When I ask pip3.8 to upgrade itself, it removes the installed pip3.7:

# pip3.8 install --upgrade pip
Collecting pip
  Using cached https://files.pythonhosted.org/packages/54/0c/d01aa759fdc501a58f431eb594a17495f15b88da142ce14b5845662c13f3/pip-20.0.2-py2.py3-none-any.whl
Installing collected packages: pip
  Found existing installation: pip 19.2.3
    Uninstalling pip-19.2.3:
      Successfully uninstalled pip-19.2.3
Successfully installed pip-20.0.2


# head -n1 /usr/local/bin/pip3.*
==> /usr/local/bin/pip3.6 <==
#!/usr/bin/python3

==> /usr/local/bin/pip3.8 <==
#!/usr/local/bin/python3.8

为什么这样做,如何防止呢?

Why is it doing this, and how can I prevent it?

更新:

  • 两个安装的lib路径不同,如下所示:
# python3.7 -c 'import sys; print(sys.path)'
['', '/usr/local/lib/python37.zip', '/usr/local/lib/python3.7', '/usr/local/lib/python3.7/lib-dynload', '/usr/local/lib/python3.7/site-packages']
# python3.8 -c 'import sys; print(sys.path)'
['', '/usr/local/lib/python38.zip', '/usr/local/lib/python3.8', '/usr/local/lib/python3.8/lib-dynload', '/usr/local/lib/python3.8/site-packages']

  • 这不是双向的-升级 pip3.7 不会删除 pip3.8 .

    我相信已正确升级,并将版本3.7库保留在原位,只是删除了shell wrapper脚本.在 pip3.8 升级之后:

    I believe the library gets upgraded correctly and leaves the version 3.7 library in place, it's just the shell wrapper script that's deleted. Here's after the pip3.8 upgrade:

    # python3.7 -m pip --version
    pip 20.0.2 from /usr/local/lib/python3.7/site-packages/pip (python 3.7)
    # python3.8 -m pip --version
    pip 20.0.2 from /usr/local/lib/python3.8/site-packages/pip (python 3.8)
    # pip3.7 --version
    bash: pip3.7: command not found
    # pip3.8 --version
    pip 20.0.2 from /usr/local/lib/python3.8/site-packages/pip (python 3.8)
    

    • 执行 pip3.7 install --upgrade pip 不会删除/usr/local/bin/pip3.6 ,因此并非如此总是删除以前的版本.

      • Doing pip3.7 install --upgrade pip does not remove /usr/local/bin/pip3.6, so it's not the case that it always removes previous versions.

        为获得完全的可重复性,并显示我从一个相当原始的系统开始,这是一个包含我的Dockerfile文本的Gist: https://gist.github.com/kenahoo/a1104f9cb84694fbd5ec9d6d560a885e .由于 pip3.7 丢失了,因此在 RUN pip3.7 install setuptools numpy pandas 行上失败.

        For full reproducibility, and to show that I'm starting with a fairly pristine system, here's a Gist containing my Dockerfile text: https://gist.github.com/kenahoo/a1104f9cb84694fbd5ec9d6d560a885e . It fails on the RUN pip3.7 install setuptools numpy pandas line because pip3.7 has gone missing.

        我是否使用 python3.8 -m pip install --upgrade pip或 pip3.8 install --upgrade pip 升级都没关系,他们两个最终都删除了/usr/local/bin/pip3.7 包装器脚本.

        It doesn't matter whether I upgrade using python3.8 -m pip install --upgrade pip or pip3.8 install --upgrade pip, both of them end up removing the /usr/local/bin/pip3.7 wrapper script.

        推荐答案

        我相信我找到了问题.

        简而言之,将 pipX.Y 控制台脚本设置为用于构建 pip 滚轮的Python解释器的版本,而不是该版本的用于安装它的Python解释器.

        In short, the pipX.Y console script is set to the version of the Python interpreter used to build the pip's wheel, instead of the version of the Python interpreter used to install it.

        例如,将安装在任何 Python 中的 pip 安装在 非 3.8(在我的例子中是 Python 3.6)并使用它下载 pip 本身:

        For example take any pip installed in any Python that is not 3.8 (in my case it's Python 3.6) and use it to download pip itself:

        $ /path/to/pythonX.Y -m pip download pip
        

        这应该为您提供一个 wheel 文件,例如 pip-20.0.2-py2.py3-none-any.whl ,现在将其解压缩:

        This should give you a wheel file for example pip-20.0.2-py2.py3-none-any.whl, now unzip it:

        $ /path/to/pythonX.Y -m zipfile -e pip-20.0.2-py2.py3-none-any.whl .
        

        现在查看 pip-20.0.2.dist-info/entry_points.txt 的内容:

        $ cat pip-20.0.2.dist-info/entry_points.txt 
        [console_scripts]
        pip = pip._internal.cli.main:main
        pip3 = pip._internal.cli.main:main
        pip3.8 = pip._internal.cli.main:main
        

        所以即使我有Python 3.6,也有一个控制台脚本 pip3.8 条目.这显然是错误的.例如,如果我确实有一个实际的 pip3.8 脚本,则该文件在卸载与Python 3.6相关的 pip 时将被删除,例如进行升级.

        So there is an entry for a console script pip3.8 even though I have Python 3.6. This is obviously wrong. And for example if I indeed had an actual pip3.8 script then this file would be deleted when uninstalling the pip associated with the Python 3.6, for example to upgrade it.

        问题的根源可以在这里看到,例如:

        The root of the issue can be seen here for example:

            entry_points={
                "console_scripts": [
                    "pip=pip._internal:main",
                    "pip%s=pip._internal:main" % sys.version_info[:1],
                    "pip%s.%s=pip._internal:main" % sys.version_info[:2],
                ],
            },
        

        此行 pip%s.%s = pip._internal:main%sys.version_info [:2] 实际上是在构建 wheel 时实际记录下来的,并且我假设我们先前下载的 wheel 是使用 Python 3.8 构建的.

        This line pip%s.%s=pip._internal:main" % sys.version_info[:2] gets actually written down definitely when building the wheel, and I assume the wheel we downloaded earlier was built with Python 3.8.

        pip 的维护者,并且不确定它是否会得到修复(可能不值得).

        That bug is (at least partially) known to pip's maintainers, and not sure it will get fixed (probably not worth it).

        无论如何,应该始终使用显式的/path/to/pythonX.Y -m pip 代替. pip * 脚本只是为方便起见而在此处使用的快捷方式.它们在交互式命令行中很有用,可以节省一些击键并能够更快地工作.但是在文件中,从文档到 shell 脚本或 Dockerfiles 的任何文件,我都认为应该始终使用显式扩展版本.例如,我总是写 rm --recursive 而不是 rm -r 等.

        Anyway, one should always use the explicit /path/to/pythonX.Y -m pip instead. The pip* scripts are just shortcuts that are here for convenience. They are somewhat useful from an interactive command line to save some keystrokes and be able to work faster. But in a file, anything from documentation, to shell scripts, or Dockerfiles, I am the opinion that one should always use the explicit expanded versions. For example I always write rm --recursive instead of rm -r, etc.

        Python pip 的一种特殊情况下,无论如何,这都是有道理的:

        Additionally in the one particular case of Python's pip, it makes sense no matter what:

        这篇关于升级`pip`会删除其他python的pip的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆