Разработчик на Python
0,0
рейтинг
13 декабря 2013 в 22:55

Разработка → Почему я ненавижу virtualenv и pip перевод

Я не разделяю всеобщей любви к virtualenv (далее — venv) и pip. Я считаю, что они лишь вносят неразбериху и более того — вредят. Python-программисты чаще всего не соглашаются со мной, да и venv+pip де-факто считается стандартом в python-сообществе. Так как я понимаю, насколько голословными звучат мои высказывания, решил написать сей трактат. Конечно, я иногда пускаюсь спорить на эту тему и в реальной жизни: и ну нравится мне заводить людей и наблюдать, как страстно они остаивают свою позицию. Но при этом мне всегда кажется, что словесно я не могу обосновать свою позицию в полной мере. Поэтому вместо того, чтобы постоянно пытаться вербально доказывать свою точку зрения, я решил написать эту статью, дабы потом просто показывать её людям. Может быть тогда некоторые со мной согласятся, потому что сейчас не согласен почти никто. А может наоборот, как только мои доводы будут всецело поняты, найдутся те, кто их аргументированно опровергнет. Так или иначе, я буду рад любому варианту развития событий.

venv и иллюзия изоляции

Изоляция и легко воспроизводимое чистое python-окружение безо всяких скрытых зависимостей от основной операционной системы это, определённо, хорошая вещь. Основная цель venv — предоставление удобного способа изоляции на уровне python'а. Но тут не всё идеально: для тех пакетов питона, которые зависимы от системных библиотек, изоляция осуществляется лишь частично, распространясь только на python-составляющую этих пакетов. Если разработчик в курсе этого — всё еще не так плохо, но вот если нет — он может столкнуться с серьёзными и непонятными ему проблемами.

Полные методы изоляции приводят к избыточности venv

Есть несколько методов изоляции всей файловой системы. Самый полный, но тяжеловесный способ — это использование виртуальной машины под гипервизором. Такую функциональность обеспечивает ряд программ, таких как Vagrant. С другой стороны существуют легковесные решения, например chroot, либо легковесные контейнеры, работающие на уровне операционной системы, например на Linux это LXC. Причём LXC может использовать copy-on-write файловую систему вроде btrfs для создания среды окружения с большей скоростью и меньшими затратами дискового пространства, чем даже в случае с venv.

venv это антипаттерн развёртывания

Я чувствую раздражение некоторых читателей при упоминании таких технологий как LXC. Да, на практике мы не всегда можем обеспечить совместимость нашей целевой среды окружения с LXC. И не всегда мы можем предоставить LXC требуемые ей права суперадмина (и ведь всё это лишь для того, чтобы просто развернуть наше приложение!)
Но я считаю, что и venv тоже не подходит для развёртывания. Почему? Как упоминалось в начале, изначальная цель venv — это лишь обеспечение удобного доступа пользователя к интерактивно создаваемой python-песочнице. Развёртывание же это по крайней мере полуавтоматический и легко повторяемый процесс. Таким образом попытка автоматизировать venv, чтобы заставить его автоматически делать то, что на нём удобнее делать вручную, видится более сложной и нетривиальной задачей, нежели просто установить переменную окружения PYTHONPATH в качестве входной точки программы. Очень просто установить через pip какой-нибудь огромный пакет, вроде Django, в произвольную папку (через опцию prefix). По крайней мере гораздо проще, чем косвенно управлять venv и путаться с многочисленными shebang'ами. И не забывайте о том, что с venv по сути у вас отсутствует контроль за целевой средой окружения, и вам приходится вежливо просить админинистратора компьютера, на котором происходит развёртывание, чтобы тот установил в саму операционную систему клиентские mysql библиотеки и заголовочные файлы; всё это для того, чтобы вы просто смогли скомпилировать mysql-python для развёртывания!
Распространять коммерческое ПО непросто, и venv в этом не помощник.

venv полон костылей

Когда вы устанавливаете venv, он на самом деле не пуст. В директорию lib/ копируется вся стандартная библиотека питона. В include/ — пачка питоньих заголовочных файлов. Смысл существования этих директорий кажется мне надуманным (подробнее в следующем параграфе), но гораздо больше меня раздражает bin/. В bin/ лежат pip и easy_install. venv портит shebang'и их обоих, чтобы запускать их не под системным, а под лежащим в той же директории интерпретатором python'а. Shebang'и всех прочих скриптов от дополнительно установленных пакетов портятся точно таким же образом. И вам приходится поддерживать это поведение venv и следить за shebang'ами постоянно, пока вам нужно работать со скриптами, лежащими внутри venv, «снаружи», например, запуская их через системный cron. Вам приходится «захардкоживать» путь к соответствующим venv, чтобы скрипт запускался под нужным интерпретатором. Это, как минимум, так же утомительно, как и вручную настраивать PATH/PYTHONPATH. На самом деле, проще ничего не делать, но я вернусь к этому чуть позже.

Ой, я забыл упомянуть bin/activate

Который устанавливает переменную окружения PATH и меняет вашу строку ввода в консоли. Если вам всегда было по нраву это, и вы считали это передовой технологией, что ж, поздравляю, похоже, вы жили в танке. Впрочем, как и ваш скрипт. .NET разработчики под Windows смеются над вами.

--no-site-packages

venv уродует sys.path двумя способами. Опция --sytem-site-packages присоединяет site-packages venv'а в начало существующего списка путей, тем самым, становится возможным использовать глобально установленные модули питона внутри venv. Есть также опция --no-site-packages, которая включена по умолчанию, и которая, как можно догадаться, этого присоединения не совершает. Видимо, именно поэтому копии некоторых библиотек вроде stdlib и заголовочных файлов положены беспорядочно свалены прямо внутри venv. Собственно, факт существования этой опции, а также тот факт, что она выставлена по умолчанию, на мой взгляд, говорят сами за себя. Очевидно, сторонники venv не желают иметь скрытые зависимости между пакетами в системе и venv; как и не желают, чтобы пакеты неправильных версий случайно просачивались внутрь venv. Однако их любимый venv всегда появляется в самом начале списка путей, так что небольшая вероятность всё равно присутствует (нет, я не забыл о команде pip freeze — о ней поговорим позже). Это опасение может показаться излишним, но вот в чём парадокс. По сути, venv никогда и не обеспечивал 100% изоляцию! Какая польза от того, чтобы вы на 100% уверены в том, что вы не используете системную версию mysql-python в то время, как вы на 100% уверены, что используете системную версию libmysqlclient! Невозможно одновременно частично использовать изоляцию и частично игнорировать её!

pip и venv это отличная связка

Все так думают лишь потому, что они написаны одним и тем же человеком — Ian Bicking. У обеих программ своя собственная философия и свои собственные варианты использования. Мне не нравится venv по большей части потому, что он заставляет людей верить, но я допускаю, что у него есть своя ниша. На самом деле я сам им пользуюсь время от времени для быстрых одноразовых тестов. Но pip с другой стороны не должен был рождаться вообще. Он — лишь «почти-совместимая» альтернатива easy_install с дополнительными свистоперделками, которых бы лучше не было вовсе. Заместо него я предпочитаю использовать easy_install вкупе с такими интерактивными и не очень программами как puppet или вообще компиляцией пакетов из исходников. Может показаться, что у меня предвзятость против pip, но это не так. Я согласен, что в чём-то приятнее писать в консоли pip install, нежели easy_install. easy_install звучит как-то глупо. Да и нижнее подчёркивание в имени это явно не практично. Готов поспорить, что одно лишь имя обеспечивает pip'у некоторую часть его популярности.

pip каждый раз собирает из исходников

eggs в питоне это как jars в джаве
Кажется, pip умышленно был лишён возможности easy_install устанавливать пакеты из бинарников (eggs). Несмотря на то, что распространение бинарников было значимой частью python-платформы и, кстати, вполне работоспособной, видимо, кто-то решил, что это плохая идея. Конечно, с точки зрения разработчиков, компиляция пакетов из исходников есть очевидное благо, которое позволяет им не компилировать предварительно пакет под каждую из всех поддерживаемых платформ (а переложить это на несомненно обрадованного этим пользователя — прим. пер.). Но компиляция становится злом в том случае, если целевых платформ немного, и вы точно знаете её/их и хотели бы собрать пакет заранее, избавившись от необходимости иметь компилятор на целевом компьютере (.NET- и Java-разработчики снова смеются над вашими проблемами). Но самая большая тупость в том, что если вы используете venv с опцией --no-site-packages, то каждый раз каждому члену вашей команды, развёртывая venv внутри SOE в ходе процесса разработки, приходится пересобирать все модули. И это поистине глупо, ведь вы даже их не разрабатываете и ни малейшего смысла в постоянной пересборке просто нет.

Этот чёртов requirements.txt

Чтобы объявить необходимые зависимости для своего пакета, можно указать их в install_requires в setup.py. Это python way. setuptools/distribute реализуют этот механизм, и он используется как easy_install, так и pip для автоматической загрузки с Pypi и установки этих зависимостей. По причинам, которые слишком долго объяснять, pip также позволяет указать список зависимостей в текстовом файле. Обычно он называется requirements.txt. Его синтаксис точно такой же, как в setup.py, но у него также есть возможность дополнительно вложить файлы, в которых пути к зависимостям могут быть указаны в виде файловых путей, URI и даже ссылок на Mercurial- / Git-репозитории (про всё это мы поговорим в следующем параграфе).

Я согласен, что эти функции здорово расширяют возможности, но я не верю, что именно они являются причиной существования requirements.txt. По-моему, реальная причина в том, что все Python-проекты делятся на два класса: пакеты, которые не используются самостоятельно и лишь импортируются в существующие проекты и, собственно, сами эти проекты. Те разработчики, которые пишут лишь приложения, не вполне понимают все особенности создания пакетов, поэтому, недолго думая, просто «захардкоживают» весь ассортимент используемых ими модулей в своё приложение, просто перечисляя их в requirements.txt, ведь это так удобно! Эти разработчики чаще всего просто советуют пользователям установить venv, а затем накатить в него свой пакет командой pip install -r requirements.txt.

В результате мы имеем некоторое количество python-разработчиков, которые считают requirements.txt панацеей от всех проблем. Они даже никогда не узнают о существовании setuptools. Их легко покоряет кажущимся простым тупое перечисление ссылок на необходимые пакеты, лежащие где-то в недрах интернета: на сайтах или в системах контроля версий. Меня обескураживает их святая уверенность в «фантастической» прагматичности этого подхода и вытекающем отсюда желании пропагандировать использование virtualenv+pip как связки незаменимых инструментов для всех и каждого.

URI в качестве путей к зависимостям это отстой

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

Если вы в requirements.txt указываете путь к локальному файлу или к лежащему на каком-нибудь сайте тарболлу, по факту вы захардкоживаете эту ссылку. Хотя в данном случае лучшим выходом было бы использование репозитория пакетов. Который позволил бы людям, например, настроить зеркала на него в своей локальной сети. Кроме того, вы не можете указать минимальную версию, лишь только точную текущую. А в один прекрасный день тот самый файлик с пакетом переместится или удалится, в общем, пропадёт, и код внезапно перестанет работать. Совершенно очевидно, что мы этого не хотим, ведь так?

Что ж, есть другой способ. Давайте указывать зависимости таким способом:
git+https://github.org/my/stupid/fucking/package#egg=1.2.3

Но он требует от пользователя иметь на компьютере git, кроме того pip'у приходится выкачивать полную копию репозитория. А чаще люди и вовсе не используют версионную нотацию (1.2.3 в примере — прим. пер.) и предполагают, что стабильная версия должна лежать в ветке master. Всё это печально. Я знаю, что сейчас модно ставить всё подряд прямо из систем контроля версий, но «хардкордить» эти URL в ваш проект? И без того спорное решение, становящееся совсем неоправданным, если всё можно сделать правильно, просто немного попотев над правильной настройкой setup.py.

Если вам по нраву pip freeze, с вами что-то не так

У меня хорошо получается отслеживать свои зависимости и управлять ими. Я делаю это с помощью pip freeze. Команду pip freeze используют для того, чтобы убедиться, что никакие Python-зависимости не были упущены посреди цикла разработки. Если вы полагаете, что pip freeze выдаёт вам список зависимостей как раз для вставки в requirements.txt (который, напомню, не нужен) — тогда вы просто используете --no-site-packages (который тоже не нужен) при создании нового venv, и весь набор зависимостей всё равно получается глобально-системным, а не питоньим. А, и кроме того, таким образом не узнать, какие из ваших зависимостей установлены напрямую, а какие подтянуты другими.

С другой стороны можно, обнаружив, что эти зависимости порушили вашу среду окружения, попытаться просто пересоздать её. Но с venv+pip это займёт у вас целую вечность (напомню, нужно будет пересобрать всё и вся). В то время как с LXC CoW и уже собранными в бинарные eggs пакетами (всех зависимостей, с которыми вы не работаете в данный момент), вы очень быстро обнаружите недостающие зависимости — как на системном уровне, так и непосредственно питоньи.
В целом pip freeze не такая уж плохая команда, всё дело в том, что люди слишком часто считают её незаменимой, не принимают во внимание её недостатки и используют не по назначению.

Заключение

Это мой критикующий, при этом полностью субъективный и, может, в чём-то даже спорный анализ полезности как программ virtualenv и pip, так и сложившейся вокруг них программерской культуры. Мне очень нравится питон как язык, но меньше — как платформа, потому что она фрагментирована различными стандартами распространения пакетов и стандартами процесса разработки. Лично в моём случае это приводит к тому, что я трачу на борьбу с Питоном больше времени, нежели на работу с ним. Я регулярно общаюсь с разными умными людьми, которые искренне верят, что venv и pip обеспечивают всё, что им нужно для разработки, совместной работы и развёртывания готовых приложений. Я же во время разработки не использую ни venv, ни pip.
И я надеюсь, что эта статья, как минимум, докажет читателю, что можно и нужно понимать принцип работы этих программ и при этом критически относиться к ним.

От переводчика:
Разработчикам, работающим под Windows: независимо от того, решили вы отказаться от pip или просто ищете способ устанавливать некоторые пакеты, которые не хотят сходу ставиться с pip (например падающие с ошибкой unable to find vcvarsall.bat), а на сайтах разработчиков пакетов, скомпилированные версии не предоставляются, могу посоветовать чудесный сайт, собирающий под своим крылом всевозможные скомпилированные пакеты во всевозможных версиях: Unofficial Windows Binaries for Python Extension Packages
Перевод: Andrew, platform-agnostic python developer
@lightman
карма
22,0
рейтинг 0,0
Разработчик на Python
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

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

  • +1
    А как RVM и Bundler выглядят на этом фоне?
    • +6
      // Все, что я напишу ниже это мое мнение, если у кого-то это вызывает боль — рекомендую выключить компьютер, и пойти почитать книжку.

      RVM Намного функциональнее venv'a. Да, тоже изменяется текущее окружение, Но в целом удобнее.

      Bundle и Gem, отличии от мира питона где зоопарк решений в руби Bundler используется везде. В pip нам на работе приходится иметь 2 файла; install_requirements, dev_requirements, при этом install_requirements обрабатывается sed'ом перед деплоем.

      Я не знаю над чем там смеются .Net'щики, но каждый раз когда мне надо скачать новый .Net чтобы запустить 5 мегабайтную программу я не смеюсь.

      Что касается деплоя: зачем там venv и rvm? Не нужен зоопарк версий на продакшен сервере. Bundle, да, нужен. pip насколько я знаю несправляется без venv если надо несколько приложений.

      По удобству инструменты в мире питона отстают от руби и прочее на световые года. Впрочем не уступает питону только php и go.
      • +5
        Я не знаю над чем там смеются .Net'щики, но каждый раз когда мне надо скачать новый .Net чтобы запустить 5 мегабайтную программу я не смеюсь.
        Вообще говоря фреймворка достаточно самого последнего. Вы же не удивляетесь, что периодически приходится обновлять версию ruby?
        А смеются потому что дотнету (равно как и яве) не нужна изоляция от системы. Просто не нужна и всё. Работает подход «всё своё ношу с собой». Положил набор managed dll-ок в дистрибутив (именно в дистрибутив, так-то всё извлекается NuGet-ом), и знаешь, что заведётся как надо. А нативных зависимостей у дотнета практически никогда нет (клиент MySql, например, полностью на C#, без всяких libmysqlclient и прочего мусора). А если и есть, то компилировать всё равно ничего не надо, так как нативные сишные функции импортируются через P/Invoke с поздним связыванием. В принципе, всё то же самое относится к Java, разве что там JNI вместо P/Invoke.
        • +2
          Так на ruby и не пишут настольные приложения. Мой то вброс был на тебу десктопных приложений на .Net. например ваш клиент для vpn'a работает neo4en в ubuntu.

          В руби тоже можно FFI использовать для вызова сишнего кода без какой либо компиляции. И тот же JNI в случае с jRuby. Что касается Java — опять зоопарк: maven2, maven3, gradle, sbt, ant и наверное еще 10 штук. Без своего хранилища артефактов вообще сложно существовать. Но «все свое ношу с собой» мне нравится.

          > (клиент MySql, например, полностью на C#, без всяких libmysqlclient и прочего мусора)

          Это исключительно следствие того, что C# быстрее ruby и python'a. У нас в python проекта едиственная нативная зависимость это libmemcached.

          > Вообще говоря фреймворка достаточно самого последнего.

          Тогда почему меня установлено все доступные фрэимворки для Win 7? Руками я их не ставил никогда. И еще куча VC++ redistributable установлено начиная с 2005 года.

          > А смеются потому что дотнету (равно как и яве) не нужна изоляция от системы.

          В руби и питоне тоже можно без изоляции обойтись если зависимостями заниматься так же как в Java и .NET. А больше одной версии ruby надо только некоторым разработчикам и CI.

          • 0
            касается Java — опять зоопарк: maven2, maven3, gradle, sbt, ant и наверное еще 10 штук.

            Там или оно поверх maven так или иначе или аналоги make. Фактически же лучше использовать maven и те системы что эксплуатируют его инфраструктуру тем или иным способом. В этом случае со сборкой, зависимостями и деплоем проблем не возникает.

            Это исключительно следствие того, что C# быстрее ruby и python'a. У нас в python проекта едиственная нативная зависимость это libmemcached.

            Это исключительно в следствие того что C# писался с оглядкой на Java. А там как-то либы все за редким исключением написаны на java.
            • 0
              > Там или оно поверх maven так или иначе или аналоги make. Фактически же лучше использовать maven и те системы что эксплуатируют его инфраструктуру тем или иным способом. В этом случае со сборкой, зависимостями и деплоем проблем не возникает.

              Это если я начинаю новый проект. Я вот начал sbt использовать, начальник использует maven, потом решили все под gradle перевети. Они конечно мощные инструменты, но maven требует столько лишнее текста, что никакого желания нет его использовать.

              > Это исключительно в следствие того что C# писался с оглядкой на Java. А там как-то либы все за редким исключением написаны на java.

              Так и Java на медленная. Был бы .Net медленный использовали бы FFI. У нас на работе есть проект у которого в зависимостях javacv. Самая отвратная бибилиотека которую я только видел, а подключить нормальную не хотят потому, что не православно.
              • 0
                Они конечно мощные инструменты, но maven требует столько лишнее текста, что никакого желания нет его использовать.

                maven так многословен в силу того что он не просто система сборки и управления зависимостями. По этой причине требует чтения документации и вдумчивого написания конфига.

                У нас на работе есть проект у которого в зависимостях javacv. Самая отвратная бибилиотека которую я только видел, а подключить нормальную не хотят потому, что не православно.

                Использование либы через JNI как правило дает много головняка и проблем при развертывании.
          • 0
            Тогда почему меня установлено все доступные фрэимворки для Win 7?
            У вас там две версии рантайма (.NET 2.0/.NET 4.0) и обновления базовой библиотеки классов (3.0/3.5/4.5). Если у вас установлен 3.5, то он спокойно запустит приложение для 2.0. Mono вот вообще сиренево, что там и где, запускает бинарники, собранные под любой дотнет.
            например ваш клиент для vpn'a работает neo4en в ubuntu.
            Наш клиент VPN сейчас вообще написан на Qt 4.7. Со старым начались проблемы из-за того что наркоманы из каноникал отменили системный трей, не сделав при этом для GtkStatusIcon слоя эмуляции, как для QSystemTrayIcon (sni-qt). Кстати, какие именно затруднения у вас возникают? Я ни разу за последнее время проблем не испытывал с ним.
            В руби и питоне тоже можно без изоляции обойтись если зависимостями заниматься так же как в Java и .NET
            Но этого никто не делает. В результате развёртывание приложений на ruby превращается в ад, особенно если не знать про существование RVM и копипастить команды из инструкции по установке.
            • +1
              > Кстати, какие именно затруднения у вас возникают? Я ни разу за последнее время проблем не испытывал с ним.

              Очень не стабильно работал в отличи от openvpn'a.

              > Но этого никто не делает. В результате развёртывание приложений на ruby превращается в ад, особенно если не знать про существование RVM и копипастить команды из инструкции по установке.

              Как это не делает? При правильном деплои bundle всегда делает «бандл» зависимостей. А rvm нужен только если надо несколько версий руби в одном окружении, что весьма плохая идея, зачем делать шаред хостинг на руби? О каком аде идет речь? Один раз настроить capistrano, и разворачивай любое приложения сколько хочешь.
              • 0
                Очень не стабильно работал в отличи от openvpn'a
                Так клиент — это морда к консольному openvpn, которая общается с демоном на сервере, позволяя проворачивать такую штуку как смену IP без переподключения Оно не может работать лучше или хуже openvpn…
          • 0
            Вы, наверное, имели в виду ivy, а не ant.
            Вообще ibiblio довольно хорошо работает. Другое дело, что maven, когда я последний раз с ним работал, напрочь не имел возможности автоматического разрешения версий.
        • НЛО прилетело и опубликовало эту надпись здесь
          • 0
            Не нужна. Самый последний вполне в состоянии запустить те, что от предыдущих. Там суть в чём:

            1) всего было 3 версии рантайма основного 1.0, 2.0 и 4.0. 3.0, 3.5 и 4.5 — это обновления базовой библиотеки классов, то есть если у вас в системе есть .NET 3.0, а приложению нужен 2.0, то оно спокойно запустится. С версиями рантайма несколько сложнее. 2.0 в состоянии запустить приложения собранные под 1.0/1.1 (я ни одного такого не видел, правда, но тем не менее), а вот между 4.0 и 2.0 есть набор несовместимых изменений, которые несущественны, но тем не менее для того чтобы .NET 4.0 согласился запустить exeшник, собранный под .NET 2.0, необходимо чтобы у того в манифесте было чётко прописано, что новый рантайм его не удивит.

            Как-то вот так.
            • 0
              Периодически бывают изменения, которые ломают обратную совместимость. Канонический пример — принципиальное изменение семантики Enumerable.Cast при переходе с 3.5 на 3.5 SP1 (сломались все, кто делал Cast<int>() на IEnumerable<double> и тому подобные вещи).
      • +7
        Как-то получил я Ruby-проект, установил RVM, сделал cd в директорию проекта… и увидел, как крашится терминал. Опытные рубисты, наверное, сразу догадались бы, что дело в .rvmrc, в котором были прописаны криквые комманды, но представьте моё удивление, когда обычный, абсолютно безопасный cd начал стабильно убивать консоль.

        RVM обеспечивает свою функциональность за счёт магии с перехватом комманд. Кому-то нравится магия, кому-то нет. Кто-то любит Rails за автоматическую генерацию кода, а кто-то предпочитает Django с его явными зависимостями. Это вопрос предпочтений, но никак не отставания.
        • –3
          Какая еще магия перехвата комманд? Обычная манипуляция с PATH там. А то, что cd начал крашить терминал это какая-то магия, если делать cd в каталог с .rvmrc, rvm сначала спросит использовать его или, в крайнем случае выдаст ошибку, что такая версия руби не устновлена. В вашей ситуации видать какую-то не понятную магию туда добавили.
          • +3
            Ок, я активирую RVM, делаю cd в директорию с .rvmrc. Откуда терминал знает, что ему нужно прочитать .rvmrc?
          • 0
            Обычная манипуляция с PATH в chruby и, в некоторой степени, в rbenv. А rvm переопределяет команду cd.
            • +4
              Ок, возможно, я нечётко выразился. RVM заставляет стандартные команды выглядеть иначе. cd — это хороший пример. Когда я меняю директорию в терминале, я ожидаю, что я просто сменю директорию. Я не ожидаю, что будет выполнен какой-то скрипт. Это магия, вклинивание в стандартные комманды. Это может быть удобно, да, но также может вести к неожиданным последствиям.

              virtualenv также манипулирет PATH-ом, но не делает ничего неожиданного. Он обещает сделать песочницу со своим питоном и библиотеками, и делает именно это. Он не пытается заменить что-то существующее, если его об этом специально не попросить. Кто-то может считать это недостатком, но Python Zen недвусмысленно намекает, что explicit is better than implicit.
              • 0
                По-моему, Вы ошиблись комментарием. Я не вступаю в спор о правильности или неправильности поведения rvm, хотя лично я использую chruby не в последнюю очередь из-за избытка магии в rvm. Но здесь я просто ответил на фразу о том, что он всего лишь меняет PATH, тогда как это не так.
                • 0
                  Оу, по выравниванию комментариев почему-то решил, что это ответ на мой комментарий. Извиняюсь.
            • +2
              Опционально:
              Перегружает команды оболочки, такие как cd. Это опасно и может привести к ошибкам.
              Перегрузка cd опциональна. Я искал суммарно почти 8 часов за последний месяц, чтобы найти проект, который перегружает cd — и что вы думаете? Не нашёл. В любом случае, RVM предоставляет возможность смотреть на тот код, который будет исполнен при запуске cd до момента его исполнения и выбирать, доверять ему или нет.
              • 0
                Но было включено по умолчанию несколько лет назад, когда я использовал rvm. Собственно, по Вашей же ссылке: habrahabr.ru/post/131968/#comment_4389739
                Если сейчас в rvm нет тех проблем, которые были пару лет назад — это просто чудесно, я рад за использующих rvm.
        • +1
          От исполняемого .rvmrc rvm ушёл в сторону декларативного .ruby-version, в нём же поддерживаются и gemset'ы.
      • 0
        Многие любят ставить RVM и на продакшне. Сталкивался несовместимостей версии Ruby с определёнными библиотеками, причём даже среди MRI, что уж говорить, когда какой-то worker запускается с JRuby, а основное приложение — на 1.9.3, тут без RVM никак.
        Сам по себе RVM тот ещё инструмент, его можно сравнить с бензопилой, в инструкции к которой написано «не пытайтесь остановить полотно руками или половыми органами», потому что такие случаи случались. Отучить людей делать system-wide install просто невозможно.

        Bundler и RubyGems хороши, но пока дело не доходит до сотни установленных gem'ов. Стоит посмотреть протокол, по которому они работают с rubygems.org, и становится реально страшно. Новый Dependency API просто перекладывает работу на сервер, создавая дикую нагрузку, при этом заниматься улучшениями, в отличии от неимоверного числа коммиттеров в Rails, никто не хочет.
  • 0
    Гм, и ни слова про buildout
    • +2
      buildout — довольно глючная вещь. Не раз сталкивался с тем, что он просто отказывается работать, без объяснения причин (невнятная ошибка, по которой непонятно, куда копать). А также с тем, что не ставились новые версии зависимостей (явно прописанные в конфигурации), не применялись патчи (возможно, проблема конкретной реализации recipe, но от этого не легче ), и т.д. и т.п.
      • +1
        много лет пользуюсь, никаких проблем
  • +8
    как в старом добром анекдоте:
    "- что-то мне, индейцы, ваш вождь не нравится…
    — не нравится — не ешь."

    Да, инструмент не идеален.
    Да, он подходит для большинства случаев.
    Нет, негативные эмоции — плохие помощники в любом деле.
  • +1
    Во-во, а потом спрашивают, зачем нужен девопс. Девопс нужен, чтобы установка чего-либо в систему не была «особо согласовываемым действием».
  • 0
    Пользуюсь buildout, согласен с автором.
  • +6
    Как-то сильных фактов автор не привел, осуждает venv за то, что он уродует ему шибэнги, а pip не работает с яйцами. Для 99% использования они подходят хорошо, а остальное можно допилить (да и нельзя сделать универсальный инструмент на все случаи жизни).
    Единственное, с чем могу согласить с автором, так это не полной изолированности venv, его нельзя взять, упаковать и перенести на другой сервер :(
    Да что там на другой сервер, недавно обновлял os x и venv созданые под 10.8 перестали работать под 10.9, т.к. питон поменял версию с 2.7.3 на 2.7.5 и не все либы почему-то он стал видеть. Пришлось создавать новый venv и ставить все заново, правда заняло это 5 минут
  • +8
    image
    image
    • +3
      Distribute 0.7.3: «This package is a simple compatibility layer that installs Setuptools 0.7+.»
    • +1
      Проект Distribute, который развивался как форк setuptools, официально больше не поддерживается, его код слит обратно с setuptools. Теперь остались только setuptools и pip. Distutils2 тоже загнулся.
  • –1
    Подскажите, как бороться с такой проблемой:
    # pip install rosinstall-generator
    Downloading/unpacking rosinstall-generator
      Could not fetch URL https://pypi.python.org/simple/rosinstall-generator/: There was a problem confirming the ssl certificate: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:550)>
      Will skip URL https://pypi.python.org/simple/rosinstall-generator/ when looking for download links for rosinstall-generator
      Could not fetch URL https://pypi.python.org/simple/: There was a problem confirming the ssl certificate: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:550)>
      Will skip URL https://pypi.python.org/simple/ when looking for download links for rosinstall-generator
      Cannot fetch index base URL https://pypi.python.org/simple/
      Could not fetch URL https://pypi.python.org/simple/rosinstall-generator/: There was a problem confirming the ssl certificate: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:550)>
      Will skip URL https://pypi.python.org/simple/rosinstall-generator/ when looking for download links for rosinstall-generator
      Could not find any downloads that satisfy the requirement rosinstall-generator
    Cleaning up...
    No distributions at all found for rosinstall-generator
    Storing complete log in /root/.pip/pip.log
    

    Иногда проходит команда, а иногда — выдает такую ошибку.
    • НЛО прилетело и опубликовало эту надпись здесь
      • 0
        Стоит последний pip2, openssl и поставил ca-certificates. Не помогает.
        Пришел на работу со своим ноутом, там установилось. В общаге вылезает ошибка, что выше.
        • НЛО прилетело и опубликовало эту надпись здесь
          • 0
            Спасибо, но не работает. Выдает Error <urlopen error [Errno 1] _ssl.c:507: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed> while getting pypi.pytho)
            А как эту проверку вообще отключить?
            • НЛО прилетело и опубликовало эту надпись здесь
  • +5
    У меня на текущий момент всего пару пунктов вызывают недовольство:

    1. чтобы поставить пакет нужно установить libSOMETING-dev или тулзу необходимую для сборки, причем можно долго и упорно выяснять это по всем зависимостям
    2. virtualenv можно сломать установкой/обновлением/удалением пакетов или обновлением системы и в эти моменты нужно догадаться что что-то пошло не так и пересоздать окружение
    3. он никак не защищает от того что автор пакета может удалить свой пакет или конкретную версию с pypi
    4. скачивание и сборка пакетов может занимать много времени, для частых развертований это может быть довольно критичным

    Я не скажу что у меня огромный опыт в других пакетных системах для питона, но контейнеры и виртуалки для изоляции python окружения в большинстве случаев все же считаю оверкилом, а buildout за кратковременное знакомство совсем не зацепил. То что не нужны рутовые права (в большинсве случаев), не нужно менять (ломать) основную систему (в большинсве случаев), можно быстро развернуться считаю хорошим плюсом.
    • +1
      Если билдить нативные пакеты прямо с готовым virtualenv, то все проблемы решаются:
      1) Нужно только на билд машине
      2) В нативном пакете прописываем жесткие зависимости от системных пакетов
      3) Свое зеркало pypi или whl
      4) Cвое зеркало pypi или whl или просто включить cache в ~/.pip/pip.conf

      Лично меня напрягает ровно одна вещь — идеологичесая:
      Пакетные менеджеры были в частности созданые еще и для того, чтобы каждая баблиотека была установлена 1 раз. Скажем если вам нужен python-django, то вы его ставите 1 раз для всех проектов. Иначе получается .NET (фреймворк у нас на каждой машинке, а все остальное носим с собой).
      Но может это только личные терзания.
      • 0
        Все же для dev окружения многое остается.

        Как я понял Вы имеете ввиду зависимости от системных питоновских пакетов, если так, то получается, что специфические версии используемых яиц также должны быть собраны, или же собираем всесь проект с virtualenv и установленными зависимотсями в пакет OS?

        За whl спасибо.
        • +1
          Да. Вот, например, если вы используете MySQL-python, то понятно что на билд машине вы должны поставить libmysqlclient-dev.
          Собираем все через virtualenv + pip install -r reqs.txt и в получившемся пакете жестко прописываем libmysqlclient18 (= 5.5.34)
          Если вдруг злой админ решит поставить что-то другое или удалить этот пакет, то он получит уведомление от пакетного менеджера, что нужно решить конфликт. В этом случае для вас не будет неожиданностью ситуация и вы будете осознанно действовать. Других способов сломать virtualenv я не знаю, но не исключено что они есть.

          Вот кстати еще ссылок на подумать:

          hynek.me/talks/python-deployments/ вот этот вот чувак считает, что все нужно раскладывать в нативные пакеты.
          И даже предлагает тулзу, которая умеет кастовать пакеты из python/gem/другие в deb/rpm/другие (https://github.com/jordansissel/fpm)
          Не лишено смысла, но ооочень трудозатратно. Потому что фактически у вас будут посчи все пакеты новые относительно stable репозитория. И все придется собрать, хоть и один раз. Ну и не трудно догадаться, что все зависимости придется расписывать самому (а это могли бы сделать за нас разрабы либ, но им тоже влом :)

          А вот ребята из Mozilla docs.services.mozilla.com/server-devguide/release.html другого мнения.
          Если коротко, то они фактически пихают все в virtualenv и пакуют его вместе с кодом в нативный пакет (у них это rpm).
          Не по феншую, зато топорно просто.
  • +8
    Заместо него я предпочитаю использовать easy_install

    Once you easy_install, there's no easy uninstall
  • +4
    Резюмируюя:
    1. локальные пакеты есть добро
    2. virtualenv не даёт полной изоляции для локальных пакетов
    3. подходящих альтернатив нет
  • +3
    Почти все описанные автором проблемы происходят из того, что pip используется на продакшене. В случае если приложение собирается в пакет для целевой операционной системы, все операции с pip и venv происходят на билд-машине, а админу/клиенту приезжает все уже в готовом виде и только с необходимыми зависимостями.
  • +7
    Много правильных моментов в статье, но автор не предлагает никаких путей их решения.
    • 0
      но автор не предлагает никаких путей их решения

      Это меня тоже удивило. В комментах к оригинальной статье, автор тоже кроме упоминание LXC более никак тему не раскрывает.
    • 0
      А кто-нить находил вообще аналоги или хотя бы предложения по решению проблем?
  • +1
    Подозреваю, что Вам так и не удалось переубедить коллег в спорах, раз даже целую статью написали.
    А все потому, что при всей неидельности pip + venv в разы ускоряет разработку и deploy, а эмоциональной-идеологический батхерт отнимает время и нервы.
    • +4
      Это перевод :)
  • +4
    Интересно знает ли автор, что venv включили в стандартную библиотеку Python 3.3.?
    • +2
      PEP 453 его точно добъет.
  • –2
    Только что на канале одного питоновского проекта:
    a: hi
    a: ?how can I update X if I use pip to install it?
    b: a: does normal pip install -U X work?
    a: i would like to update
    a: i dont try with command
    a: i'll try one moment
    a: b: I get this message with this command
    a: Could not find any downloads that satisfy the requirement X in /usr/local/lib/python2.7/dist-packages
    a: Downloading/unpacking X
    a: Cleaning up…
    a: No distributions at all found for X in /usr/local/lib/python2.7/dist-packages
    a: Storing complete log in /root/.pip/pip.log
    b: a: are you using virtualenv?
    a: no

    Косвенное свидетельство в пользу того, что люди считают, что «pip и venv это отличная связка».

    Кстати, как называется, когда узнаешь о чем-то и почти сразу сталкиваешься с этим независимо?
    • –2
      Рандом?
  • 0
    Интересно, как автор относится к virtualenvwrapper. :)
    • +2
      Вообще-то также.
      Sets PATH and changes your prompt. If you find this exciting, you’ve been living under a rock. Same goes for virtualenv wrapper. .NET developers on Windows are mocking you.

      Virtualenvwrapper только делает создание и работу с виртуальным окружением удобнее. Вы же не можете использовать virtualenvwrapper без virtualenv:)
  • +1
    virtualenv + pip это **не** система дистрибуции софта. Это способ разработки. На выходе все равно должен получиться .tar.gz с кучей *.wheel-ов или нечто другое инсталлябельное.

    А если так, то разрабатываться можно так как удобно — никто тут ничего не навязывает. Тот же кто использует virtualenv+pip для обновления продакшна — дурак и всё.
    • –1
      p.s. ну и чего нам тут с переводчиком дискутировать что ли? :-D

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.