http://habrahabr.ru/post/261263/
TL;DR
Чтобы просто установить и изолировать зависимости проекта,
virtualenv часто оказывается слишком тяжелым решением. Предлагаем простую альтернативу:
- добавить
./.pip
в переменную окружения PYTHONPATH
,
- установить пакеты локально с помощью
pip install -t .pip
,
- запускать
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
Шаг 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-пакетов.