Обновление `pip` удаляет другие python пипсов - PullRequest
4 голосов
/ 09 апреля 2020

В системе CentOS 7 у меня установлено несколько версий Python, каждая с собственной версией 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:

# 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

Почему это происходит и как я могу предотвратить это?

ОБНОВЛЕНИЯ :

  • Пути 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 на месте, это просто сценарий оболочки оболочки, который удаляется. Вот после обновления pip3.8:

# 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, поэтому не всегда происходит удаление предыдущего версии.

  • Для полной воспроизводимости и для демонстрации того, что я начинаю с довольно нетронутой системы, вот Gist, содержащий мой текст Dockerfile: https://gist.github.com/kenahoo/a1104f9cb84694fbd5ec9d6d560a885e. В линии RUN pip3.7 install setuptools numpy pandas происходит сбой, потому что пропал pip3.7.

  • Не имеет значения, обновляюсь ли я с использованием python3.8 -m pip install --upgrade pip или pip3.8 install --upgrade pip, оба они заканчиваются удаление сценария оболочки /usr/local/bin/pip3.7.

Ответы [ 2 ]

1 голос
/ 09 апреля 2020

Кажется, я нашел проблему.

Короче говоря, консольный сценарий pipX.Y настроен на версию интерпретатора Python, использованного для построения колеса pip . вместо версии интерпретатора Python, использованной для его установки.

Например, возьмите любой pip установлен в любом Python, то есть , а не 3.8 (в моем случае это Python 3.6), и используйте его для загрузки pip:

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

Это должно дать вам файл wheel , например pip-20.0.2-py2.py3-none-any.whl, теперь распакуйте его:

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

Итак, есть запись для консольного скрипта pip3.8, хотя у меня есть Python 3.6. Это явно неправильно. И, например, если бы у меня действительно был скрипт pip3.8, то этот файл был бы удален при удалении pip , связанного с Python 3.6, например, для его обновления.

root проблемы можно увидеть здесь, например:

    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] получает на самом деле записано определенно при сборке колеса , и я предполагаю, что колесо , которое мы скачали ранее, было построено с Python 3.8 .


Эта ошибка (хотя бы частично) известна сопровождающим pip , и она не уверена, что это будет исправлено (вероятно, не стоит).

В любом случае, вместо этого всегда следует использовать явное /path/to/pythonX.Y -m pip. Сценарии pip* - это просто ярлыки, которые приведены здесь для удобства. Они несколько полезны из интерактивной командной строки, чтобы сохранить некоторые нажатия клавиш и иметь возможность работать быстрее. Но в файле, что угодно, от документации до shell сценариев или Dockerfiles , я считаю, что всегда следует использовать явные расширенные версии. Например, я всегда пишу rm --recursive вместо rm -r, et c.

Дополнительно в одном конкретном случае Python s pip, имеет смысл независимо от того, что:

1 голос
/ 09 апреля 2020

Обновление

Вы можете использовать команду pip target, чтобы сообщить пипу, где разрешено искать пип и выполнять обновление.

$ pip3.8 install --upgrade --target /usr/local/lib/python3./site-packages/ pip

Для обновления просто pip3.8, который оставит pip 3.7 без изменений.

Когда я запустил

...

RUN pip3.5 install --upgrade --target /usr/local/lib/python3.5/site-packages/ pip
RUN pip3.6 install --upgrade --target /usr/local/lib/python3.6/site-packages/ pip
RUN pip3.7 install --upgrade --target /usr/local/lib/python3.7/site-packages/ pip
RUN pip3.8 install --upgrade --target /usr/local/lib/python3.8/site-packages/ pip

...

pip все еще находился в пакетах сайта для python3 .5 / 3.6, но pip3.5 & 3.6 обнаружил не в /usr/local/bin. Таким образом, для установки пакетов глобально в python3 .5 / 3.6 необходимо использовать python3.5 -m pip install <package>

Это потому, что pip3.5 и pip3.6 должны храниться в /usr/bin не /usr/local/bin. Вы можете использовать

...

RUN pip3.5 install --upgrade pip
RUN pip3.6 install --upgrade pip
RUN pip3.7 install --upgrade --target /usr/local/lib/python3.7/site-packages/ pip
RUN pip3.8 install --upgrade --target /usr/local/lib/python3.8/site-packages/ pip

...

И pip3.5-8 все будет существовать и работать. По-прежнему рекомендуется использовать виртуальные среды с python.

Warning

Pip, похоже, выдает предупреждение, вызванное прямым вызовом pip. В предупреждениях предлагается вызывать pip как python модуль, продвигающийся вперед python -m pip <command>

[root@93e6e7373eff /]# pip3.8 -V
WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip.
Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue.
To avoid this problem you can invoke Python with '-m pip' instead of running pip directly.
pip 20.0.2 from /usr/local/lib/python3.8/site-packages/pip (python 3.8)

[root@93e6e7373eff /]# pip3.7 -V
WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip.
Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue.
To avoid this problem you can invoke Python with '-m pip' instead of running pip directly.
pip 20.0.2 from /usr/local/lib/python3.7/site-packages/pip (python 3.7)

[root@93e6e7373eff /]# pip3.6 -V
pip 20.0.2 from /usr/local/lib/python3.6/site-packages/pip (python 3.6)

[root@93e6e7373eff /]# pip3.5 -V
pip 20.0.2 from /usr/lib/python3.5/site-packages/pip (python 3.5)


Обходной путь

Я смог заставить все это работать изменив порядок, в котором вы устанавливаете. Поскольку, похоже, единственная проблема заключается в том, что pip3.8 ищет старые версии и удаляет их, я установил и обновил их прежде всего. Я только что построил это на своем ноутбуке, и он работал (лол, это работало на моей машине).

# -*- dockerfile -*-
FROM centos:7.7.1908
RUN yum update -y
RUN yum install -y epel-release
RUN yum install -y https://centos7.iuscommunity.org/ius-release.rpm

RUN yum install -y python35u python35u-pip
RUN yum install -y python36u python36u-pip

RUN yum install -y gcc gcc-c++
RUN yum install -y make openssl-devel bzip2-devel libffi-devel

# Python3.8 is not currently available from RHEL, EPEL, or IUS repos so download and compile it
ARG PY38_VERSION=3.8.2
RUN cd /usr/src && curl https://www.python.org/ftp/python/${PY38_VERSION}/Python-${PY38_VERSION}.tgz | tar -xz &&\
  cd Python-${PY38_VERSION} && ./configure --enable-optimizations && make -j4 altinstall &&\
  rm -rf /usr/src/Python-${PY38_VERSION}

RUN pip3.8 install --upgrade pip
RUN pip3.8 install setuptools numpy pandas

# Python3.7 is not currently available from RHEL, EPEL, or IUS repos so download and compile it
RUN yum install -y gcc openssl-devel bzip2-devel libffi-devel make sqlite-devel
ARG PY37_VERSION=3.7.6
RUN cd /usr/src && curl https://www.python.org/ftp/python/${PY37_VERSION}/Python-${PY37_VERSION}.tgz | tar -xz &&\
  cd Python-${PY37_VERSION} && ./configure --enable-optimizations && make -j4 altinstall &&\
  rm -rf /usr/src/Python-${PY37_VERSION}

RUN pip3.7 install --upgrade pip
RUN pip3.7 install setuptools numpy pandas

RUN pip3.5 install --upgrade pip
RUN pip3.5 install setuptools numpy pandas
RUN pip3.6 install --upgrade pip
RUN pip3.6 install setuptools numpy pandas


RUN yum install -y python35u-devel python36u-devel python37u-devel python38u-devel


CMD /bin/bash

выходы с консоли:

[root@e3b166a8b479 /]# python3.7 -m pip -V     
pip 20.0.2 from /usr/local/lib/python3.7/site-packages/pip (python 3.7)
[root@e3b166a8b479 /]# python3.6 -m pip -V
pip 20.0.2 from /usr/local/lib/python3.6/site-packages/pip (python 3.6)
[root@e3b166a8b479 /]# python3.8 -m pip -V
pip 20.0.2 from /usr/local/lib/python3.8/site-packages/pip (python 3.8)
[root@e3b166a8b479 /]# ls /usr/local/bin | grep pip
pip
pip3
pip3.6
pip3.7
pip3.8
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...