Привет, мой друг!
Предположу, что для управления Python окружением в вашем проекте до сих пор используется pip и virtualenv.
Если это так, то позвольте рассказать о таком инструменте, как Pipenv.
Pipenv — это современный инструмент для управления рабочим окружением в Python.
Основные возможности pipenv:
- Создание и управление виртуальным окружением
- Синхронизация пакетов в Pipfile при установке и удалении пакетов
- Автоматическая подгрузка переменных окружения из .env файла
В качестве показательного примера сравним использование pip и virtualenv с pipenv для создания виртуального окружения:
pip и virtualenv
$ virtualenv venv $ source venv/bin/activte $ pip install Flask gunicorn $ pip freeze > requirements.txt
pipenv
$ pipenv install Flask gunicorn
Начало работы
Установим последнюю версию pipenv:
$ pip install pipenv
Управление рабочим окружением
Перейдем в каталог с Python проектом и создадим виртуальное окружение указав версию интерпретатор:
$ cd yourproject
$ pipenv --python 3.7
Команда автоматически создаст новое виртуальное окружение для вашего проекта, если он еще не существует.
Активировать виртуальное окружение проекта можно выполнив команду shell
:
$ pipenv shell
Выход из оболочки виртуального окружения осуществляется с помощью команды exit
:
$ exit
Управление зависимостями приложения
Для установки пакетов воспользуемся командой install
:
$ pipenv install Flask
Pipenv установит последнюю версию пакета Flask
и автоматически добавит его в Pipfile.
При установке можем задать конкретную версию пакета:
$ pipenv install Flask==1.0.2
Разработчики данного инструмента позаботились и о работе со средой разработки — пакетами, которые необходимы на этапе сборки или тестирования приложений.
При указании флага --dev
, пакет будет установлен как часть среды разработки:
$ pipenv install pytest --dev
Чтобы установить все пакеты, включая пакеты среды разработки необходимо выполнить:
$ pipenv install --dev
Для удаление пакетов существует команда uninstall
:
$ pipenv uninstall Flask
Сведения об установленных пакетах и их зависимостях хранятся в файле Pipfile.lock, который генерируется автоматически и не должен быть изменен пользователем.
Запуск исходного кода
Существует возможность запуска исходного кода внутри оболочки virtualenv:
$ pipenv run python yourapplication.py
При наличии файла .env команды $ pipenv shell
и $ pipenv run
, автоматически подгрузят из него переменные окружения:
$ cat .env
DEBUG=1
$ echo $DEBUG
1
Развертывание приложения
Pipenv позволяет устанавливать зависимости в родительскую систему при указании флага --system
:
$ pipenv install --system
Это полезно при развертывания приложений в Docker.
При указании флага --deploy
— pipenv выдаст ошибку, если Pipfile.lock устарел или версия Python не соответсвует указанной.
Пример Dockerfile для работы с pipenv:
FROM python:3.7
RUN pip3 install pipenv
WORKDIR /usr/src/app
COPY Pipfile ./
COPY Pipfile.lock ./
RUN set -ex && pipenv install --deploy --system
COPY . .
Пример приложения на Flask с использованием возможностей Pipenv: github.com/fdhadzh/flask-pipenv-example.
Комментарии (34)
iroln
06.07.2018 09:46В Pipfile можно задать интерпретатор вот так:
[requires] python_version = "3.5"
Почему разработчики pipenv не хотят сделать возможность задавать несколько версий Python?
Есть вот такие закрытые issue, например, где они довольно резки и категоричны:
https://github.com/pypa/pipenv/issues/1050
Хотя в том же PEP-508 на котором основана эта разработка явно прописано, что можно задавать несколько версий
https://www.python.org/dev/peps/pep-0508/
Можно же создавать venv и Pipfile.lock для разных версий интерпретатора. А как сейчас указать в Pipfile, что мы поддерживаем, скажем Python 2.7 и >=3.4? Или я и все эти люди из issue что-то не понимаем?
Также они [разработчики] почему-то решили, что разделение окружений на dev и default хватит всем, но, очевидно, это не так. Мне, например, как минимум нужны ещё testing и doc. И я не один такой:
https://github.com/pypa/pipenv/issues/726
https://github.com/pypa/pipenv/issues/2303
Но разработчики как всегда категоричны:
not happening. explicitly designed for just two groups.
Смотря на всё это… а как на счёт poetry?
fdhadzh Автор
06.07.2018 10:07Да, pipenv не серебряная пуля, но удовлетворяет большинству требований типовых приложений.
А poetry действительно заслуживает отдельного внимания. Спасибо!
sortarage
06.07.2018 10:07Я в Python весьма неопытный, можно очень кратко, в чем кардинальное различие между pipenv и venv+pip? Какое-нибудь офигенное удобство, или фича, которую другими решениями, можно решить только велосипедами?
immaculate
06.07.2018 10:57Некоторые незначительные преимущества есть, просто они в данной статье вообще не рассмотрены. Но я использую virtualenv + fish + virtualfish, и пока для себя не вижу резона переходить на pipenv. Надо возможно поиграться с ним на каком-нибудь проекте, может быть, тогда почувствую преимущества.
kammala
06.07.2018 12:11+1Основное отличие pipenv — это наличие файла Pipfile.lock, содержащего список версий всех пакетов, установленных в этом окружении, с их зависимостями + md5 сумма файла пакета.
Это дает воспроизводимость сборки. Например, нет проблемы, когда вы протестировали свой код на CI 2 дня назад, а во время раскатки на production приехала обновленная версия какой-то из зависимостей, несовместимая с вашим кодом(несколько раз натыкался на такое в связке aiohttp — yarl).
Наличие же md5 дает некоторую защиту от атаки MITM и внедрения вредоносного кода при установке на другое окружение.sklavit
06.07.2018 15:25conda умела контролировать версии установленных пакетов и проверять зависимости и до pipenv и не только не даст поставить несовместимое, но и подберет такой полностью совместимый набор версий для всех пакетов environment-а.
kammala
06.07.2018 23:22в моем случае в
requirements.txt
был указан толькоaiohttp
, который по зависимостям подтянул обратно несовместимую версиюyarl
.
в случае с pipenv при выполнении команды
pipenv install aiohttp==2
генерируется Pipfile.lock, в котором прописан
aiohttp == 2.0.5
,yarl == 0.9.3
(версии указаны для примера). На этой установке прогоняются тесты и в production пойдут именно эти версии пакетов.
в случае с обычными
requirements.txt
после установки каждого пакета надо руками запускатьfreeze
и, возможно, очищать его от каких-то локальных пакетов.
как это работает вconda
с егоenvironment.yml
я не смог найти, буду признателен за ссылку.pesh1983
07.07.2018 16:17А если в вашей системе есть другой пакет, которому нужна другая версия yarl, pipenv эту ситуацию разрулит?
pesh1983
07.07.2018 16:14Мне вот правда интересно, были ли в реальности случаи осуществления MITM по отношению к пакетной системе Питона? Я понимаю, что если даже ничего такого не было, это не значит, что ничего такого произойти не может. Но с таким же успехом вы можете изначально поставить подмененный пакет, рассчитать для него хэш) Такая защита выглядит странно. Для исключения подмены пакетов уже давно придумана pgp подпись)
kammala
07.07.2018 23:09не скажу за питон, но в целом проводятся атаки на пакетные менеджеры, например, на npm.
вообще, я думаю, тут скорее не от MITM защита, а именно от скачивания иной версии пакета, нежели та, на которой проводилось тестирование(например, если мэйнтейнер перезалил пакет не поменяв версию), но в целом наличие такой валидации лучше, чем ее отсутствие.
pesh1983
07.07.2018 16:15Я для фиксации версий есть pip freeze. Так что мне совсем непонятны преимущества данной тулзы)
kammala
07.07.2018 22:14pip freeze
не делает фиксации версий, он просто показывает версии пакетов, установленных в данном окружении.
там могут быть указаны системные пакеты, если, например, окружение собрано с флагом--system-site-packages
, что в общем случае нежелательно и создает дополнительную головную боль.
pipenv
решает эту проблему в полуавтоматическом режиме.pesh1983
07.07.2018 22:20pip freeze > requirements.txt
pip install -r requirements.txt
Первая команда фиксирует, вторая — инсталлирует все запиненные версии. По поводу флага, никогда не сталкивался с такой сборкой питона в рабочих проектах, мы везде испоьэльзуем виртуальное окружение, и такой проблемы не наблюдаем. Но, если у вас такая проблема есть, то, да, наверное, pipenv тут поможетkammala
07.07.2018 23:01да понятно, просто в случае с pipenv все эти команды выполняются оболочкой за разработчика — это удобно(одна команда вместо 2) и более безопасно(про pip freeze можно, например, попросту забыть).
такая сборка имела смысл в доисторические времена, когда еще не было wheel, а пакеты под windows распространялись в виде exe и ставить в virtualenv их было невозможно.
vovochkin
06.07.2018 12:55+1В статье сравнивается работа pip и pipenv на двух примерах. pip:
pipenv:$ virtualenv venv $ source venv/bin/activte $ pip install Flask gunicorn
$ pipenv install Flask gunicorn
А почему pipenv показан не так?
$ pip install pipenv $ pipenv shell $ pip install Flask gunicorn
Я pipenv не использовал и предубеждений против него не имею, просто любопытно.fdhadzh Автор
06.07.2018 15:06+1Для формирования файла зависимостей приложения (requirements.txt) с помощью pip и virtualenv необходимо создать и активировать виртуальное окружение, установить пакеты и "заморозить" их. При использовании pipenv нет необходимости в активации виртуального окружения, команда
install
создаст окружение, если оно отсутствует, установит пакеты и добавит их в Pipfile.
Senpos
06.07.2018 15:35+1А почему pipenv показан не так?
Удобство. Обо всем по порядку.
pip install pipenv
Вы единожды ставите пакет в систему и больше его не трогаете. Поэтому нет смысла указывать этот шаг при сравнении двух этих инструментов.
$ pipenv shell
$ pip install Flask gunicorn
А это не альтернатива.
shell
используют, если вам нужно проделывать много манипуляций из-под этогоvirtualenv
. Если вам нужно установить пакеты или запустить скрипт — зачем?
Для установки же пакетов очень удобно использовать
$ pipenv install <package>
, который автоматически посмотрит, есть ли в данной папкеPipfile
, создано ли окружение, если нет — создаст, установит в это окружение пакеты и "запинит" зависимости.
pip install <package>
же этого всего не сделает, даже если запускать его внутриshell
. Да, он установит пакет вvirtualenv
, но "пинить" зависимости вам придется самим.pesh1983
08.07.2018 17:18А что делать, если я хочу потестировать новый пакет, но пинить мне не надо? Обычно это поведение менеджеров по умолчанию, что npm, что pip и это вполне обоснованное решение. Если разработчик хочет зафиксировать версии пакетов, которые у него есть в о окружении и раскатить эти изменения на всех, и на прод в том числе, он должен сделать это явно. А такое поведение с фиксацией по умолчанию может сыграть злую шутку.
Senpos
08.07.2018 22:09А что делать, если я хочу потестировать новый пакет, но пинить мне не надо?
pipenv install <package> --skip-lock
он должен сделать это явно
Тут явно делается обратное. Вы всегда хотите запинить версии. А если нет — пожалуйста, вот флаг.
pesh1983
08.07.2018 22:28Ну, как я уже написал, это потенциальное поле для проблем) Если я набираю команду install, я ожидаю именно install, а не pin, deploy или ещё что-нибудь бонусом) В общем, в лучших антпаттернах Питона, потому как это совсем не explicit is better than implicit.
pesh1983
07.07.2018 16:09Есть такая крутая штука, называется pyenv. Там вам и любая версия питона и автоматическая активация окружения при входе в нужную папку. Советую )
Senpos
07.07.2018 22:49Эту "штуку"
Pipenv
вполне себе поддерживает.
А еще много других, крутых фишек. Все в одном пакете, с удобным CLI.
Советую более детально ознакомиться на официальном сайте проекта.
Проект активно развивается, но я, например, пока не перешел на него. Производительность хромает (по крайней мере на Windows), некоторые решения разработчиков в дизайне инструмента сомнительны (в Issues много интересных обсуждений).
Присматриваюсь к
poetry
, попутно используя старый добрыйpip
+venv
.pesh1983
07.07.2018 23:34Я и не писал, что pipenv не поддерживает pyenv) Я вот ещё раз перечитал по вашей ссылке список фичей и для меня честно плюсы этого инструмента очень сомнительны по сравнению с остальными. Давайте пройдемся по каждому пункту отдельно:
- You no longer need to use pip and virtualenv separately. They work together.
Это реально проблема для разработчика? Ну поставьте pyenv, он решает эту проблему, да еще и добавляет возможность ставить любую версию питона и на базе него создавать окружения, автоматически их активировать при входе в папке, деактивировать при выходе и так далее без всяких доп. pipenv shell комманд.
Managing a requirements.txt file can be problematic, so Pipenv uses Pipfile and Pipfile.lock to separate abstract dependency declarations from the last tested combination.
Вот это должно стоять первым пунктом и пожалуй единственная стоящая фича всего проекта — разделение зависимостей от явно установленных пакетов. Но это решается и без pipenv. Может и не так элегантно) Но ставить только для этого отдельную тулзу как-то избыточно, что ли.
Hashes are used everywhere, always. Security. Automatically expose security vulnerabilities.
От установки изначально неправильного или подмененного пакета это никак не защищает.
Strongly encourage the use of the latest versions of dependencies to minimize security risks arising from outdated components.
А это вообще зло. С одной стороны, ребята пишут, что жестко пинят версии, а потом пишут, что поощряют использовать самые последние версии зависимостей. В моей практике, даже обновление зависимостей может повлечь неконтролируемое изменение поведения кода, поэтому обновлять зависимости, как и установленные пакеты, нужно очень осторожно. И лучше это делать явно, руками и поднимать версии на нужные, а не на самые последние. Поэтому это бы я записал не в преимущество, а скорее в недостаток.
Give you insight into your dependency graph (e.g. $ pipenv graph).
Эмм, ну да, полезная штука наверное. За более пятилетний опыт разработки на питоне не разу с такой проблемой не сталкивался. Но, если она реально у кого-то возникает, то да, тут без pipenv наверное не обойтись.
Streamline development workflow by loading .env files.
А включать в тулзу, которая управляет пакетами, функционал чтения и активации файлов, которые к управлению пакетами вообще не имеют никакого отношения, — по мне так моветон. Для этого есть direnv и аналоги, которые именно для этого и предназначены и работают не только для питона (я, например, использую его и для проектов на node, go и так далее). А зачем эта функция в менеджере пакетов, непонятно.
Senpos
08.07.2018 10:19Это реально проблема для разработчика?
Конечно, это невероятно упрощает работу. Раньше нужно было делать несколько вещей и следить за ними самому (где создавался
venv
, активировал ли я его), а тут всё сделали за меня.
поставьте pyenv, он решает эту проблему, да еще и добавляет возможность ставить любую версию питона и на базе него создавать окружения
Поставить инструмент хуже, чем инструмент лучше? Странное предложение. Тем более, что
pipenv
умеет использоватьpyenv
, поэтому минусов никаких на выходе не получаем.
Но это решается и без pipenv. Может и не так элегантно) Но ставить только для этого отдельную тулзу как-то избыточно, что ли.
Нет, не избыточно. Это автоматизация рутинного процесса в инструменте, который я буду использовать каждый день. И другие разработчики тоже. А то все городят свой костыль.
От установки изначально неправильного или подмененного пакета это никак не защищает.
А суть фичи не в этом, а в том, чтобы оповещать разработчика о версиях пакетов, которые известны наличием уязвимостей. Это круто. Лучше когда оно есть, чем когда нет, согласитесь.
. С одной стороны, ребята пишут, что жестко пинят версии, а потом пишут, что поощряют использовать самые последние версии зависимостей.
Они "пинят", в
Pipfile.lock
. А коли же вы его потеряли — изPipfile
установятся последние версии пакетов, если вы не укажете другое сами. Это уже в ответ на:
лучше это делать явно, руками и поднимать версии на нужные, а не на самые последние
включать в тулзу, которая управляет пакетами, функционал чтения и активации файловТут я и согласен, и нет. С одной стороны — вы правы, с другой — а зачем мне использовать какой-то дополнительный пакет, если это сделает
pipenv
? Он просто сделает внутри окружения доступным всё что есть в.env
как переменные окружения. Это даже логично звучит.Pipenv
все-таки и окружением управляет. Я скорее рад этому, чем нет.
Я допускаю, что не весь функционал
Pipenv
может быть нужен всем разработчикам, многие спокойно себе живут используя другие инструменты, но в мире Питона не было удобного способа делать свою разработку удобной, как это уже давно сделано в других "мирах" (PHP, JS, Ruby, ...). Использовать его или нет исключительно ваше право, но многие разработчики очень довольны, просто дайте ему шанс. Возможно, удасться насладиться тем, что за вас все сделали и вы можете просто заняться разработкой, а не играми с окружением и зависимостями! :)pesh1983
08.07.2018 11:14Раньше нужно было делать несколько вещей и следить за ними самому (где создавался venv, активировал ли я его)
Насколько я понял из описания инструмента, окружение все равно надо явно активировать через pipenv shell, поэтому не понимаю, чем pipenv shell отличается от. venv/bin/activate к примеру. И там и там можно забыть активировать окружение.
pyenv же активирует окружение при входе в директорию проекта без всяких pipenv shell.
Поставить инструмент хуже, чем инструмент лучше? Странное предложение. Тем более, что pipenv умеет использовать pyenv, поэтому минусов никаких на выходе не получаем.
Начнем с того, что это разные инструменты) хотя их функционал может частично пересекаться. Поэтому писать, что один инструмент хуже, чем другой, хотя их сценарии и задачи отличаться, вот это действительно странно) Я лишь предложил pyenv в качестве альтернативы автоматической активации окружения.
Нет, не избыточно. Это автоматизация рутинного процесса в инструменте, который я буду использовать каждый день.
Ну если вы каждый день обновляете пакеты, то да, это нужный функционал. В моей практике обновление пакетов выполняется ну раз в месяц, не чаще. Не потому, что лень, а потому что процесс проверки и миграции занимает время, которое не хочется тратить, если нет значимых преимуществ от обновления.
А суть фичи не в этом, а в том, чтобы оповещать разработчика о версиях пакетов, которые известны наличием уязвимостей.
А можно про это поподробнее?) Как использование хешей для файлов может оповестить о наличии или отсутствии уязвимостей в коде?
Они "пинят", в Pipfile.lock. А коли же вы его потеряли — из Pipfile установятся последние версии пакетов
То что они пинят, я понял) Просто непонятно тогда, что значит "Strongly encourage the use of the latest versions of dependencies"
Он просто сделает внутри окружения доступным всё что есть в .env
Ну если вы используете только питон, наверное, да, хороший вариант. Но если что-то, что выходит за рамки этого языка, то увы, тут pipenv будет только мешать этим функционалом, потому что в одном месте вы будете использовать стороннюю тулзу, а в проектах на питоне pipenv. Но, в целом, конечно, дело вкуса.
Вдобавок, если вы обратили внимание, то этот pipenv позиционируется разработчиками именно как менеджер среды dev окружения "Python Dev Workflow for Humans". А поэтому использовать его в проде я бы не рискнул. А при использовании его только в дев окружении теряется весь смысл, потому что на прод деплоится это будет уже по-другому.Senpos
08.07.2018 12:45окружение все равно надо явно активировать через pipenv shell, поэтому не понимаю, чем pipenv shell отличается от. venv/bin/activate к примеру
Для установки пакетов НЕ нужно активировать окружение самому. Даже для запуска скриптов можно НЕ активировать окружение самому, а воспользоваться
pipenv run <command>
, чтобы исполнить что-нибудь из нужного окружения.
Я лишь предложил pyenv в качестве альтернативы
…
Начнем с того, что это разные инструментыТак и запишем!
Еще раз.
pipenv
при желании расширяется возможностямиpyenv
. Зачем себя ограничиватьpyenv
, а остальные вещи делать руками или другими способами — непонятно.
pyenv же активирует окружение при входе в директорию проекта
На любой "платформе"?
bash
/zsh
/cmd
/powershell
?
Автоматическую активацию окружения уже давно можно сделать и просто вpip
, подключив нужный плагин в том жеzsh
. Такие же штуки есть и дляpipenv
.
Как использование хешей для файлов может оповестить о наличии или отсутствии уязвимостей в коде?
Никак, сори, я неправильно прочитал ваш комментарий. Я держал у себя в голове информацию об этом.
Просто непонятно тогда, что значит "Strongly encourage the use of the latest versions of dependencies"
Нет
Pipfile.lock
— всегда ставит последние версии пакетов, если не указано иначе.
если что-то, что выходит за рамки этого языка, то увы, тут pipenv будет только мешать этим функционалом, потому что в одном месте вы будете использовать стороннюю тулзу, а в проектах на питоне pipenv.
Не совсем понимаю, как тут будет мешать
pipenv
. Есть проект на Python, в нем есть свой.env
,pipenv
его подтянул. Никто не мешает использовать остальные тулзы.
pipenv позиционируется разработчиками именно как менеджер среды dev окружения "Python Dev Workflow for Humans"
Ну, это очевидно. Вы превращаете свой неудобный процесс разработки в удобный. :)
А при использовании его только в дев окружении теряется весь смысл, потому что на прод деплоится это будет уже по-другому.
Ничего не теряется. Даже если вы будете собирать свое приложение в Докере — вам так или иначе нужны конкретные версии пакетов, которые будут лежать в
Pipfile.lock
. А его уже разработчик будет создавать при помощиpipenv
с великим удовольствием.pesh1983
08.07.2018 14:08> а воспользоваться pipenv run То есть мне все команды запуска надо переделать? А если по какой то причине мне придется поменять инструмент, то менять команды запуска обратно. Ну да, весело наверное.
> Так и запишем!
Не стоит вырывать фразы из контекста. Я написал про альтернативу автоматической активации окружения, а не про управление зависимостями. Pyenv — это про разные версии интерпреторов и окружений на их базе и только. А pipenv в этом плане и жрец, и жнец, и на дуде игрец: и виртуальное окружение включит, и пакеты запинит, ещё и переменные окружения сам подгрузит, разве что пакет не собирает сразу под 3 платформы, и не деплоит их на сервера. А самое интересное, что без pip и virtualenv/venv он не работает, то есть по сути дублирует уже существующий функционал, но добавляет ещё расчет хэша, польза которого очень сомнительна, отделение зависимостей от явно установленных пакетов (похоже это единственный его плюс), ну и установку переменных окружения, которая к питону не имеет прямого отношения и тоже должна выполняться отдельными инструментами (поскольку, опять же, к питону напрямую не относится).
> Зачем себя ограничивать pyenv, а остальные вещи делать руками или другими способами — непонятно.
Ну если бы pipenv только управлял версиями и зависимостями в явном виде, то вопросов бы не было)
> На любой «платформе»? bash / zsh / cmd / powershell?
Насколько мне известно, да, поскольку вы прописываете его исполняемые файлы в PATH. Но я могу ошибаться, вам лучше ознакомиться с документацией.
> Нет Pipfile.lock — всегда ставит последние версии пакетов, если не указано иначе.
Вы так и не ответили на мой вопрос. Что значит «Strongly encourage the use of the latest versions of dependencies»? Об этом пишут разработчики инструмента на главной странице. Я лучше сначала разберусь, что это такое и как оно отразится на стабильности проектов, прежде чем использовать, тем более в проде ) Пока этот пункт мне непонятен.
> Никто не мешает использовать остальные тулзы.
Ну да, можно конечно. Только странно, что у вас переменные окружения будут выставляться 2 раза: сначала через pipenv, потом через другую тулзу, ну или наоборот, кто ж знает наверняка)) Даже не знаю, зачем вам такой костыль, но вам виднее) У всех разные запросы и задачи.
В заключение хочу сказать, что использование конкретного инструмента — дело сугубо индивидуальное. Но если мне нужно помимо менеджера пакетов, виртуального окружения и программы, которая подгружает переменные окружения ставить ещё инструмент, который делает всё то же самое, но не работает сам по себе ни без пакетного менеджера, ни без виртуального окружения, добавляет сомнительную функциональность, а также миграция на него и с него потребует немало времени (правка не только всех дев скриптов, но и скриптов развертывания), да ещё мне непонятны некоторые моменты в его философии, я наверное воздержусь.
aldaFy
А для чего заходить в шелл?
Почему бы просто не создать окружение командой
fdhadzh Автор
Спасибо, поправил.
aldaFy
Вы так упорно лезете в шелл… а зачем? можно и без этого вполне обойтись :)