И снова здравствуйте. В преддверии старта нового потока по курсу «Machine Learning», хотим поделиться переводом статьи, которая имеет довольно косвенное отношение к ML, но наверняка будет полезна подписчикам нашего блога.





Мариатта — разработчик из Канады, спросила в Твиттере о python -m pip, попросив рассказать об этой идиоме и объяснить принцип ее работы.

Недавно я узнала, что нужно писать python -m pip вместо обычного pip install, но теперь я не могу вспомнить от кого я это услышала. Наверное, от @brettsky или @zooba. У кого-нибудь из вас есть пост в блоге, чтобы я могла поделиться им с читателями?
— Мариатта (@mariatta) 29 октября 2019 г. (https://twitter.com/mariatta/status/1189243515739561985?ref_src=twsrc%5Etfw)



Я не уверен, что именно я сказал Мариатте о python -m pip, но есть все шансы, что это был именно я, поскольку я же просил, чтобы эта инструкция для установки пакетов с помощью PyPI писалась именно так с 2016 года. Итак, эта статья должна пояснить, что такое python -m pip и почему вы должны использовать именно ее при запуске pip.

Что такое python -m pip?


Для начала, python -m pip выполняет pip с помощью той версии Python, которую вы указали для инструкции python. Таким образом, /usr/bin/python3.7 -m pip значит, что вы выполните pip для интерпретатора, расположенного в /usr/bin/python3.7. Вы можете прочитать документацию про флаг -m, если вы не знаете, как он работает (кстати, он крайне полезный).

Зачем использовать python -m pip вместо pip/pip3?


Вы можете сказать: «Ладно, но почему я не могу просто воспользоваться pip, запустив команду pip?» Ответом будет: «Да, но контролировать вы ее будете меньше». Я объясню, что значит «контролировать меньше» на примере.

Предположим, у меня установлены две версии Python, например, Python 3.7 и 3.8 (это очень распространено среди людей, которые работают на Mac OS или Linux, не говоря уже о том, что вы возможно захотели поиграться с Python 3.8, и у вас уже стоял Python 3.7). Итак, если вы введете pip в терминале, для какого интерпретатора Python вы установите пакет?

Без более подробной информации ответа вы не узнаете. Сначала вам нужно будет понять, что лежит в PATH, то есть /usr/bin идет первым или же /usr/local/bin (которые являются самыми распространенными местами для установки Python, кстати обычно /usr/local/ идет первым). Итак, вы помните, где вы установили Python 3.7 и 3.8 и что это были разные каталоги, и вы будете знать, что пришло в PATH первым. Предположим, что вы установили оба вручную, возможно в вашей системе был уже предустановлен Python 3.7.3, и вы установили Python 3.7.5. В этом случае обе версии Python устанавливаются в /usr/local/bin. Можете ли вы сказать мне теперь, к чему теперь привязан pip?

Ответ вы не знаете. Если вы не знаете, когда устанавливали каждую версию, и понимаете, что последняя версия pip была записана в /usr/local/bin/pip, но вы не знаете, какой интерпретатор будет использоваться для команды pip. Теперь вы можете сказать: «Я всегда ставлю самые последние версии, так что это значит, что Python 3.8.0 будет установлен последним, поскольку он новее, чем, допустим, 3.7.5". Хорошо, но что происходит, когда выходит Python 3.7.6? Ваш pip использовался бы уже не из Python 3.8, а из Python 3.7.

Когда вы используете python -m pip с конкретным интерпретатором python, который вам нужен, вся неопределенность исчезает. Если я пишу python3.8 -m pip, я точно знаю какой pip будет использован и что пакет будет установлен для Python 3.8 (то же самое было бы, если бы я указал python3.7).

Если вы пользуетесь Windows, то у вас есть дополнительный стимул использовать python -m pip, поскольку он позволяет pip обновлять себя. В основном, потому что pip.exe считается запущенным, когда вы пишете pip install --upgrade pip. В этот момент Windows не позволит вам переустановить pip.exe. Однако если вы делаете python-m pip install --upgrade pip, вы обходите эту проблему, поскольку запускается python.exe, а не pip.exe.

А что происходит, когда я нахожусь в активированной среде?


Обычно, когда я объясняю суть этой статьи людям, обязательно находится кто-то, кто скажет: «Я всегда использую виртуальную среду, и это ко мне не относится». Что ж, для начала хорошо бы ВСЕГДА использовать виртуальную среду! (Я расскажу, почему я так думаю, в одной из своих следующих статей!) Но если честно, то я бы все еще настаивал на использовании python -m pip, даже если, строго говоря, это не нужно.

Во-первых, если вы пользуетесь Windows, вам все равно захочется использовать python-m pip, чтобы вы в своей среде могли обновить pip.

Во-вторых, даже если вы используете другую операционную системы, я бы сказал, что все равно нужно пользоваться python-m pip, поскольку он будет работать независимо от ситуации. Он предупредит вас об ошибке, если вы забудете активировать среду, а любой человек, который за вами будет наблюдать, будет перенимать лучшие практики. И лично я не считаю, что экономия 10 нажатий на клавиатуру – весомая цена для неиспользования хорошей практики. А еще эта команда поможет вам предотвратить ошибки при написании сценариев автоматизации, которые будут выполнять заведомо некорректные операции, если вы забудете активировать среду.

Лично я, когда пользуюсь любым инструментом, работа которого зависит от того, каким интерпретатором он запускается, всегда пользуюсь -m, вне зависимости того, активирована виртуальная среда или нет. Мне всегда важно понимать, какой интерпретатор Python я использую.

ВСЕГДА пользуйтесь средой! Не ставьте все подряд в глобальный интерпретатор!


Когда мы говорим о том, как избежать путаницы при установке в Python, хочу подчеркнуть, что мы вообще не должны устанавливать ничего в глобальный интерпретатор Python, когда работаем локально (контейнеры – это совсем другое дело)! Если это предустановленный Python вашей системы, то в случае, если вы установите какую-то несовместимую версию библиотеки, на которую опирается ваша ОС, то фактически сломаете систему.

Но даже если вы установите отдельно для себя копию python, я все равно настоятельно не рекомендую ставить прямо в нее при локальной разработке. В конечном счете в своих проектах вы будете использовать различные пакеты, которые могут друг с другом конфликтовать, и у вас не будет четкого представления о зависимостях внутри ваших проектов. Гораздо лучше использовать среды, чтобы изолировать отдельные проекты и инструменты для них друг от друга. В сообществе Python используются два типа сред: виртуальные среды и conda среды. Существует даже специальный способ изолированной установки инструментов Python.

Если вам нужно установить инструмент


Для изолированной установки инструмента, я могу порекомендовать использовать pipx. Каждый инструмент получит свою собственную виртуальную среду, чтобы не конфликтовать с другими. Таким образом, если вы хотите иметь всего одну установку, к примеру, Black, вы можете работать, не сломав случайно свою единственную установку mypy.

Если вам нужна среда для проекта (и вы не пользуетесь conda)


Когда нужно создать среду для проекта, лично я всегда обращаюсь к venv и виртуальным средам. Она включена в stdlib Python, поэтому всегда доступна с помощью python-m venv (если, конечно, вы не используете Debian или Ubuntu, в этом случае вам может потребоваться установить пакет python3-venv apt). Немножко истории: Я фактически удалил старую команду pyvenv, которую Python устанавливал для создания виртуальных сред с помощью venv, по тем же причинам, почему нужно пользоваться python -m pip вместо pip. То есть непонятно для какого интерпретатора вы создали виртуальную среду при помощи старой команды pyvenv. И помните о том, что вам не нужно активировать среду, чтобы использовать интерпретатор содержащийся в ней, ведь .venv/bin/python работает так же хорошо, как активация среды и ввод команды python.

Сегодня некоторые разработчики по-прежнему отдают предпочтение virtualenv, поскольку она доступна на Python 2 и в ней есть некоторые дополнительные функции. Лично меня мало интересуют дополнительные функции, и наличие интегрированной venv означает, что мне не нужно использовать pipx для установки virtualenv на каждой машине. Но если venv не отвечает вашим потребностям, и вы хотите виртуальную среду, то посмотрите, предлагает ли virtualenv то, что вам нужно.

Если вы используете conda


Если вы используете conda, то можете использовать среды conda для получения того же эффекта, который могут предложить виртуальные среды, предоставляемые venv. Я не собираюсь вдаваться в то, нужно ли вам использовать conda или venv в вашей конкретной ситуации, но если вы используете conda, то знаете, что вы можете (и должны) создавать среды conda для своей работы, вместо того чтобы устанавливать все подряд в свою системную установку. Так вы сможете получить четкое понимание того, какие зависимости есть у вашего проекта (и это хорошая причина, чтобы использовать miniconda вместо полноценной anaconda, поскольку в первой меньше десятой части объема последней).

Всегда есть контейнеры


Работать в контейнере – это способ не разбираться со средой вообще, так как вся ваша «машина» станет отдельной средой. До тех пор, пока вы не установили Python в систему контейнера, вы должны спокойно иметь возможность сделать глобальную установку, чтобы ваш контейнер оставался простым и понятным.

Повторюсь, чтобы вы действительно поняли суть…
Не устанавливайте ничего в свой глобальный интерпретатор Python! Всегда старайтесь использовать среду для локальной разработки!


Я уже не могу сказать, сколько раз мне приходилось помогать кому-то, кто думал, что pip устанавливал в один интерпретатор Python, а на самом деле устанавливал в другой. И это неизмеримое количество также относится к тем моментам, когда люди ломали всю систему или задавались вопросом, почему они не смогли установить что-то, что противоречило какой-то другой вещи, которую они поставили ранее для другого проекта и т.д. из-за того, что они не потрудились настроить среду на своей локальной машине.

Поэтому, чтобы и вы и я могли спать спокойно, используйте python-m pip и старайтесь всегда использовать среду.

Комментарии (19)


  1. MaZaNaX
    11.11.2019 18:33

    А разве pip --version не решает проблему с непониманием, к какой версии интерпретатора он относится?


    1. SLASH_CyberPunk
      11.11.2019 18:54

      обычно решает, но на самом деле, я столкнулся недавно с более интересной проблемой, нежели доносит автор, а именно, нельзя глобально обновить pip на cent os и если это сделать, то команда pip ломается…


      1. Tihon_V
        11.11.2019 19:34

        Попробуйте так:

        python -m pip ---user install --upgrade pip
        echo 'export PATH=$HOME/.local/python/bin:$PATH' >> ~/.bashrc


        1. SLASH_CyberPunk
          11.11.2019 19:46

          понятное дело, что через python -m pip все работает, речь про то, что все работало и через pip буквально пару месяцев назад, а теперь нет


          1. Nengchak
            12.11.2019 04:03

            на CentOS'е с таким ни разу не сталкивался. И обновлял и другой питон (рядышком) ставил. Интересно, что же у Вас пошло не так?


    1. gecube
      11.11.2019 22:52

      Решает почти наверняка, но мне тоже нравится полный контроль )


  1. roryorangepants
    11.11.2019 19:09
    +1

    >хаб Машинное обучение
    >пост про pip

    Если вы хотите попиарить свои курсы по ML, это не значит, что надо лепить левые хабы. Это значит, что надо переводить статьи по теме.


    1. neurocore
      12.11.2019 09:01

      Мне кажется многие начинающие ML-щики попадут на эту статью естественным способом в результате сёрфинга. Установить все пакеты и зависимости — та ещё морока…


  1. dominigato
    11.11.2019 19:46

    А я и не ставлю модули глобально, обычно только --user и в свой ~/.local
    Я делаю что-то плохое?


    1. worldmind
      11.11.2019 20:05

      если несколько проектов потребуют разных версий одного модуля, то будет проблема, да и просто каждый проект засоряет общее пространство модулей — при удалении проекта сложно чистить, я юзаю виртуальные окружения в xonsh, очень удобно — зашёл в папку проекта — окружение активировалось (можно и переменные окрудения нужные выставить) — вышёл — деактивировалось и переменные очистились.
      А с --user ставлю общие штуки типа httpie


      1. gecube
        11.11.2019 22:48

        А ещё лучше всякие httpie ставить через общий пакетный менеджер операционной системы, в частности, когда python пакет зависит от системных.


        Это не относится к ситуации, когда ты точно уверен, что тебе нужна версия из pypi.


      1. dominigato
        12.11.2019 02:18

        Ну я про общие штуки и говорю. Для проектов то конечно venv


    1. gecube
      11.11.2019 22:47

      Да, т.к. в python в setup.py может быть любая дичь )
      Поэтому контейнеризация — самый радикальный способ изоляции.
      Но вообще, в целом, venv надёжнее, чем --local


  1. gecube
    11.11.2019 22:46
    +1

    Не знаю чего минусуют, но все так. Полностью согласен с автором.
    Опыт — сын ошибок трудных.


  1. pawnhearts
    12.11.2019 00:16

    Есть pyenv. Есть pipenv/poetry. Можно активизировать pyenv и виртуальное окружение при переходе в каталог.


  1. DollaR84
    12.11.2019 00:42

    когда вы пишете pip install --upgrade pip. В этот момент Windows не позволит вам переустановить pip.exe.

    всегда так обновлял pip.
    У меня что-то сломано? или pip обманывает, что обновился?


    1. gecube
      12.11.2019 01:23

      У Вас точно винда? А python из какого дистрибутива? Ну, просто — для статистики.


      1. DollaR84
        12.11.2019 12:03

        windows 8.1
        python 3.5


  1. delvin-fil
    12.11.2019 06:30

    Да ладно…
    3.6 из портов(gentoo у меня), 3.8 собран из исходников в ~/.local и все работает нормально. Через pip ставится всегда локально и все видно.