Как получить "python -m venv" для прямой установки последней версии pip

На этапе компиляции новой версии python я извлекаю и запускаю get-pip.py, чтобы последняя версия pip была установлена ​​рядом с исполняемым файлом python:

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

У меня есть 25 таких версий под /opt/python, хотя в основном я использую пять последних версий каждой версии major.minor, не являющейся EOL. Чтобы настроить среду, я запускал virtualenv или мой virtualenvutils с опцией -p /opt/python/X.Y.Z/bin/python, чтобы получить виртуальную среду с определенной версией.

В 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, поскольку у него был PendingDeprecationWarning, по крайней мере, с 2014 года (как видно из выходных данных в этот вопрос)

Исследуя замену virtualenv на python -m venv в virtualenvutils, я сначала вручную создал новую виртуальную среду на основе 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! Если вы воспользуетесь им, вы получите:

You are using pip version 10.0.1, however version 18.0 is available.
You should consider upgrading via the 'pip install --upgrade pip' command

В виртуальной среде, созданной с помощью 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 тривиально выполнить несколько шагов для создания virtualenv без pip, а затем добавить pip с помощью get-pip.py. Из командной строки это не так просто:

$ /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 из /opt/python/3.7.0/lib/python3.7/site-packages/pip (python 3.7)

Что заставляет /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 был создан virtualenv с последней версией pip без возврата к сценариям, псевдонимам или использованию нескольких команд? Очевидно, недостаточно установить последнюю версию pip под /opt/python/3.7.0.

В комплекте два колеса:

/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 относится к этой проблеме, но сайт ошибок в настоящее время не работает.

Anthon 07.08.2018 09:27

Чтобы продолжить работу без предупреждений, я создал однофайловая утилита, который загружает новые файлы .whl в _bundled и обновляет ensurepip/__init__.py. Также доступно на PyPI

Anthon 07.08.2018 18:40

Чтобы обновить вручную, запустите python -m pip install --upgrade pip setuptools wheel. Не запускайте просто pip install, так как он создаст шебанг для любого установленного вами пипа по умолчанию.

dre-hh 23.11.2018 12:04
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
18
3
6 325
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Это ожидаемое поведение. python -m venv вызывает python -m ensurepip для установки pip, а Этот ответ показывает, что ensurepip установит только комплектную версию даже с опцией --upgrade. Официальной возможности обновить комплектные pip и setuptools нет.

Что ж, у меня также нет хорошей идеи исправить эту проблему, поскольку это просто спланированное поведение. Я хотел бы дать два предложения:

  1. Используйте pipenv. Это действительно хорошо! И в будущем это будет официальный менеджер пакетов следующего поколения (хотя есть большая проблема, связанная с текущей структурой Pypi. Короче говоря, менеджер пакетов может определять зависимости только при загрузке всего пакета. Это создает огромные трудности для построение графа зависимостей.).

  2. Внедрите свой собственный EnvBuilder, на самом деле об этом есть официальный пример. И в этом примере он также использует get-pip.py для установки последней версии pip.

Спасибо за ссылку envbuilder, я разберусь с этим. pipenv имеет много общего с virtualenvutils для моего варианта использования, но мне все равно придется делать ссылки на фактические исполняемые файлы в /usr/local/bin. Заявленное использование Pipfilepipenv и ужас еще одного конфигурационного файла в корне каждого проекта (в излишнем формате TOML для загрузки) делают его довольно неинтересным в долгосрочной перспективе.

Anthon 07.08.2018 10:45
pipenv не просто перекрывается с virtualenvutils, но представляет собой комбинацию pip и virtualenv, что означает, что он полностью покрывает эти два инструмента. И, кроме того, если вы решите использовать pipenv, вам больше не понадобится requirements.txt :-) На самом деле, самая большая причина, по которой я выбрал pipenv, заключается в том, что он действительно может управлять зависимостями, а не просто перечислять их, как это делает pip freeze > requirements.txt. Например, вы удаляете одну главную зависимость в Pipfile, а затем запускаете pipenv clean, она автоматически удаляет все неиспользуемые подчиненные зависимости. В конце концов, это зависит от личного мнения :-)
Sraw 07.08.2018 10:54
virtualenvutils - это не virtualenv, он делает немного больше. Поскольку я уже избавился от необходимости в requirements.txtsetup.cfg, Makefile, tox.ini, setup.py, dist, build, .tox и т. д.), Все, что pipenv помещает туда, только снова загромождает дерево разработки. Так что pipenv (для меня) - это просто лишняя работа без пользы. Всякий раз, когда я меняю зависимости, которые удаляют что-то, я сохраняю, а затем переустанавливаю утилиту и ее virtualenv с нуля (в любом случае должна быть новая микроверсия используемого Python), чтобы получить правильные зависимости (и восстановить, если это невозможно. решено).
Anthon 07.08.2018 11:12

Думаю, у нас разные сценарии использования.

Sraw 07.08.2018 11:47

Думаю, pipenv, вероятно, не следует рекомендовать в наши дни. Хотя расширение EnvBuilder выглядит интересно.

wim 14.02.2020 00:07
Ответ принят как подходящий

Я использую upgrade-ensurepip для обновления тех файлов колес pip и setuptools, которые являются частью пакета ensurepip. Это не так элегантно, как возможность обновить ensurepip через pip, но все же предпочтительнее делать это вручную.

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

Мне не нравится идея, что пользователь возится с связанными версиями пакетов (например, они могут принадлежать root и устанавливаться из диспетчера пакетов ОС, вы запутаете свою ОС, если возитесь с этими файлами)

wim 14.02.2020 00:10

Хорошая точка зрения. Я перешел на использование conda, и сейчас мне не нужно заниматься этой проблемой.

Irving Moy 24.02.2020 13:20

Хитрость заключается не в том, чтобы установить - это связанная версия pip (которая почти всегда будет устаревшей), а в том, чтобы использовать установить самую последнюю версию из Интернета.

Стандартная библиотека venv предлагает флаг --without-pip, который может здесь помочь. Создав виртуальную среду без pip, вы можете «запустить» колесо surepip напрямую благодаря импортеру zip Python. Это и быстрее, и менее опасно, чем установка 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.

venv Python 3.9 может получить опцию --upgrade-deps для автоматизации этого, см. https://bugs.python.org/issue34556 для получения дополнительной информации об этом.

Как ни странно, несколько месяцев назад я написал инструмент ve, который делает что-то в этом роде. Возможно, мне захочется его отполировать, поскольку, видимо, я не единственный, кто хочет обойти это неудобство, связанное с необходимостью обновления пип во всех виртуальных средах. Должен сделать это до выхода Python 3.9 ...

sinoroc 14.02.2020 15:05

Другие вопросы по теме