«pip -t» — простая альтернатива virtualenv

от автора


TL;DR

Чтобы просто установить и изолировать зависимости проекта, virtualenv часто оказывается слишком тяжелым решением. Предлагаем простую альтернативу:

  1. добавить ./.pip в переменную окружения PYTHONPATH,
  2. установить пакеты локально с помощью pip install -t .pip,
  3. запускать python из папки проекта.

Какую версию желаете сегодня?

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

Обычная практика — включать в проект файл requirements.txt. В этом файле перечислены все библиотеки, от которых зависит проект, с номерами версий. Если файл на месте, установить зависимости просто:

$ pip install -r requirements.txt 

Пока все хорошо. Плохо станет, если у вас два и больше проектов с конфликтующими зависимостями. Допустим, проект A работает с библиотекой X только версии 0.1, а проект B — 0.2. По умолчанию pip устанавливает библиотеки глобально в папку интерпретатора Питона. Это означает, что команда $ pip install X==0.2 установит библиотеку X версии 0.2 для всех проектов и перезапишет версию 0.1, если та уже установлена. Переключение между A и B глобальную переустановку X каждый раз, что долго и неудобно.

Остров под солнцем

Популярное решение этой частой проблемы — виртуальные окружения. Фреймворк virtualenv создает изолированные Питон-окружения. Зависимости каждого проекта отделяются друг от друга. Так или иначе, некоторым пользователям virtualenv кажется слишком сложным. Поэтому существуют пакеты типа virtualenvwrapper и autoenv, которые расширяют функциональность virtualenv, чтобы им было проще пользоваться. Другие решения: Anaconda environments и pyvenv из стандартной библиотеки Питона (3.3+).

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

В мире Яваскрипта npm и Bower предлагают простое, надежное и мощное управление пакетами, которого как будто не хватает в Питоне. Их ключ к в том, что они скачивают правильную версию правильной библиотеки и кладут ее в специальную папку внутри проекта. Скачанные библиотеки относятся только к конкретному проекту. Это автоматически избавляет от проблем, о которых говорилось выше.

Чистая магия

Оказывается, что есть простой способ повторить подход npm и Bower в Питоне:

  • добавить ./.pip в PYTHONPATH,
  • использовать pip с параметром -t .pip для локальной установки пакетов.

Затем просто запускаете код из папки проекта. Забудьте про source env/bin/activate и deactivate!

Фокус работает, потому что ./.pip — относительный путь. В результате, когда запускаете python из ~/dev/project_a, папка ~/dev/project_a/.pip включается в список папок библиотек для этого экземпляра Питона. Запускаете python в ~/dev/project_b — включается ~/dev/project_b/.pip. Прием работает на всех популярных платформах: Линуксе, Маке и Виндоузе.

Название папки .pip, конечно, может быть любым. Кому-то больше понравится pip_components или libs. Тем не менее, .pip быстро печатать, а точка в начале делает папку скрытой в Линуксе и Маке.

Шаг 1: Установить PYTHONPATH

  • MAC/LINUX

    Эта команда установит PYTHONPATH навсегда для стандартных терминальных сессий:

    $ echo 'export PYTHONPATH="./.pip:$PYTHONPATH"' >> ~/.bash_profile 

    После этого перезапустите терминал или исполните $ source .bash_profile, чтобы PYTHONPATH загрузилась в активной сессии. В зависимости от платформы вам, возможно, надо будет заменить ~/.bash_profile на ~/.bashrc.

  • WINDOWS

    Окройте Панель упраления и перейдите в System and Security → System → Change Settings → Advanced → Environment Variables (у меня английская версия, поэтому не перевожу названия разделов, чтобы случайно не запутать читателей. — прим. пер.). Добавьте или отредактируйте переменную PYTHONPATH: .\.pip или .\.pip;(...other paths...). Можно установить переменную как для пользователя, так и для всей системы.

  • TEMPORARY PYTHONPATH

    Если предпочитаете устанавливать PYTHONPATH только на время сессии, запустите $ export PYTHONPATH=./.pip в Маке и Линуксе или > set PYTHONPATH=.\.pip в Виндовсе.

    В Маке и Линуксе можно даже установить PYTHONPATH только на время Питон-сессии: $ PYTHONPATH=./.pip python main.py.

Шаг 2: Установить пакеты через pip -t

Теперь, когда PYTHONPATH установлена, осталось только установить пакеты в правильное место с помощью pip. Для этого используем ключ -t или --target:

$ cd project_a project_a$ pip install requests==2.7.0 -t .pip  project_a$ python >>> import requests >>> requests.__version__ '2.7.0' 

Теперь то же самое в другом проекте с другой версией:

$ cd project_b project_b$ pip install requests==2.6.0 -t .pip  project_b$ python >>> import requests >>> requests.__version__ '2.6.0' 

С файлом requirements.txt все работает так же:

$ pip install -r requirements.txt -t .pip 

Потенциальные засады

Разные интерпретаторы Питона

Можно легко запустить программу другим интерпретатором Питона:

$ /path/to/python main.py 

Тем не менее, есть проблема с переключением между Питоном 2 и 3, если используются пакеты, которые компилируют исходный код во время установки через 2to3. У таких пакетов нет единой кодовой базы, при установке код генерируется соответственно активной версии Питона.

В этом случае создайте папку типа .pip3 и добавьте ее в начало PYTHONPATH, когда запускаете код Питоном 3.

easy_install

Если у вас есть пакеты, установленные глобально через easy_install, столкнетесь с проблемой: easy_install дописывает путь к таким пакетам в начало sys.path, поэтому у них приоритет над пакетами из .pip.

Решение — избавиться от пакетов, установленных глобально через easy_install.

Чтобы проверить, что ничто не мешает использовать .pip, запустите import sys;sys.path в Питоне. Если перед ./.pip будут другие пути, возможно, придется сначала почистить систему от глобальных easy_install-пакетов.

ссылка на оригинал статьи http://habrahabr.ru/post/261263/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *