Ад зависимости Python: компромисс между virtualenv и глобальными зависимостями?
До сих пор я тестировал различные способы управления зависимостями моего проекта в Python:
- Установка всего глобального с помощью pip (экономит место, но рано или поздно доставляет вам неприятности)
- pip & venv или virtualenv (немного мучительно, но во многих случаях это нормально)
- pipenv & pipfile (немного проще, чем venv/virtualenv, но медленный и некоторые блокировщики, виртуальные envs прячутся где-то еще, чем папка реального проекта)
- conda в качестве менеджера пакетов и среды (отлично, если все пакеты доступны в conda, смешивать pip & conda немного смешно)
- Поэзия - я не пробовал этот
- ...
Моя проблема со всем этим (кроме 1.) заключается в том, что мое место на жестком диске заполняется довольно быстро: я не разработчик, я использую Python для своей повседневной работы. Поэтому у меня есть сотни небольших проектов, которые все делают свое дело. К сожалению, для 80% проектов мне нужны "большие" пакеты: numpy
, pandas
, scipy
, matplotlib
- вы называете это. Типичный небольшой проект содержит от 1000 до 2000 строк кода, но имеет 800 МБ зависимостей пакетов в venv/virtualenv/pipenv. Практически у меня около 100+ ГБ моего жесткого диска, заполненного виртуальными зависимостями Python.
Более того, установка всего этого в каждой виртуальной среде требует времени. Я работаю в Windows, многие пакеты не могут быть легко установлены из pip в Windows: Shapely
, Fiona
, GDAL
- мне нужны предварительно скомпилированные диски от Кристофа Гольке. Это легко, но нарушает большинство рабочих процессов (например, pip install -r requirements.txt
или pipenv install
из pipfile). Я чувствую, что я на 40% устанавливаю/обновляю зависимости пакетов и только 60% своего времени пишу код. Кроме того, ни один из этих менеджеров пакетов действительно не помогает с публикацией & тестирование кода, поэтому мне нужны другие инструменты, например setuptools
, tox
, semantic-release
, twine
...
Я разговаривал с коллегами, но все они сталкиваются с одной и той же проблемой, и ни у кого, похоже, нет реального решения. Мне было интересно, если есть подход, чтобы иметь некоторые пакеты, например, те, которые вы используете в большинстве проектов, устанавливаемых по всему миру - например, numpy
, pandas
, scipy
, matplotlib
будут установлены с pip в C:\Python36\Lib\site-packages
или с conda
в C:\ProgramData\Miniconda3\Lib\site-packages
- это хорошо разработанные пакеты, которые не часто ломают вещи. И если я хотел бы исправить это в ближайшее время в моих проектах.
Другие вещи будут идти в локальных папках virtualenv - я испытываю желание переместить мой текущий рабочий процесс с pipenv
на conda
.
Такой подход имеет смысл вообще? По крайней мере, в последнее время было много разработок в python, возможно, появилось что-то, чего я еще не видел.
Существуют ли рекомендации по настройке файлов в такой смешанной глобально-локальной среде, например, как сохранить setup.py
, requirements.txt
или pyproject.toml
для совместного использования проектов разработки через Gitlab, Github и т.д.? Каковы подводные камни/предостережения?
Также есть это отличное сообщение в блоге от Криса Уоррика, которое объясняет это почти полностью.
[Обновление]
Через полгода я могу сказать, что работа с Conda решила большинство моих проблем:
- он работает в любой системе, WSL, Windows и т.д.
- большинство пакетов уже доступно в conda-forge, легко получить собственные пакеты, принятые в conda-forge
- для тех пакетов, которые не входят в conda, я могу установить
pip
в среде conda и добавить пакеты из pypi с помощью pip
- Я могу создать строгий или открытый
environment.yml
, указав приоритет канала conda, пакеты из conda и пакеты из pip
- Я могу создать окружение conda из этих ymls в одном выражении, например настроить среду разработки в Gitlab Continuous Integration, используя
Miniconda3 Docker
- это делает тестовые прогоны очень простыми и понятными
- версии пакета в
yml
могут быть определены как строгие или открытые, в зависимости от ситуации. Например. вы можете исправить env в Python 3.6, но при этом получить все обновления безопасности в этом диапазоне версий (например, 3.6.9)
- Я обнаружил, что conda решает почти все проблемы с зависимостями, скомпилированными в c в Windows
- Что касается проблемы с "большими зависимостями": я закончил тем, что создал много специфических (то есть маленьких) и несколько неспецифических (то есть больших) сред conda: например, у меня довольно большая
jupyter_env
, где лаборатория jupyter и большая часть моей научной работы пакеты установлены (numpy, geos, pandas scipy и т.д.) - я активирую его всякий раз, когда мне нужен доступ к этим инструментам, я могу хранить их в одном месте. Для разработки конкретных пакетов у меня есть дополнительные среды, которые используются только для зависимостей пакетов (например, packe1_env
). Некоторые базовые инструменты установлены в базовой среде conda, например, pylint
.
- Я постоянно обновляюсь с Chocolatey менеджером пакетов для Windows.
choco upgrade all -Y
раз в неделю, работает как шарм!
- Новое обновление: одна из самых удивительных функций: новый флаг
--stack
позволяет накапливать среды conda, например. conda activate my_big_env
затем conda activate --stack dev_tools_env
(по состоянию на 2019-02-07) позволяет сделать некоторые пакеты общего назначения доступными во многих envs
- Новое обновление 2: я начал использовать
conda
из Windows Subsystem for Linux
(WSL), это снова улучшило мой рабочий процесс: пакеты устанавливаются быстрее, я могу работать с VS Code в Windows, напрямую подключенной к WSL, и далеко меньше ошибок с пакетами Python в среде Linux.
Один общий недостаток заключается в том, что conda становится немного медленным при использовании большого канала conda-forge. Они работают над этим, но в то же время индекс conda-forge растет очень быстро.
Ответы
Ответ 1
проблема
Вы перечислили ряд проблем, которые ни один подход не может решить полностью:
- space: "Мне нужны" большие "пакеты: numpy, pandas, scipy, matplotlib... Практически у меня есть около 100+ ГБ моего жесткого диска, заполненного виртуальными зависимостями python"
- время: "установка всего этого в каждой виртуальной среде требует времени"
- Publishing: "Ни один из этих менеджеров пакетов действительно не помогает с публикацией и тестированием кода"
- рабочий процесс: "Я испытываю желание переместить мой текущий рабочий процесс из pipenv в conda"
К счастью, то, что вы описали, не является классической проблемой зависимостей, которая мучает менеджеров пакетов - циклические зависимости, зависимости закрепления, управление версиями и т.д.
подробности
Я использовал conda на Windows много лет назад под аналогичными ограничениями с разумным успехом. Conda изначально была разработана для упрощения установки пакетов, связанных со scipy. Это все еще делает.
Если вы используете "стек Сципи" (scipy, numpy, pandas,...), Conda - ваш самый надежный выбор.
Конда может:
- установить пакеты scipy
- установить C -e xtensions и не-Python пакеты (необходимые для запуска numpy и других пакетов)
- интегрируйте пакеты conda, каналы conda (вы должны посмотреть на это) и pip для доступа к пакетам
- разделение зависимостей в виртуальных средах
Конда не может:
- помогите с публикацией кода
Воспроизводимые Envs
Следующие шаги должны помочь воспроизвести virtualenvs при необходимости:
- Не устанавливайте пакеты scipy с pip. Я бы положился на Конду, чтобы сделать тяжелую работу. Это намного быстрее и стабильнее. Вы можете установить менее распространенные пакеты внутри среды conda.
- Иногда пакет pip может конфликтовать с пакетами conda в среде (см. Примечания к выпуску, посвященные этой проблеме).
Избегайте проблем с пипсами:
A. Создайте рабочую среду отдельно от вашей базовой среды, например, workenv
. Это готовый к выполнению основной объем вашей повседневной работы.
> conda create -n workenv python=3.7 numpy pandas matplotblib scipy
> activate workenv
(workenv)>
B. Испытание установок необычных пакетов пипсов (или весомых пакетов conda) в клоне рабочей среды.
> conda create --name testenv --clone workenv
> activate testenv
(testenv)> pip install pint
C. Сделайте резервную копию зависимостей в requirements.txt
-like файл с именем environment.yaml
в virtualenv. При желании создайте скрипт для запуска этой команды для каждой среды. Смотрите документы.
Издательский
Проблема с упаковкой - это постоянная отдельная проблема, которая обрела популярность с появлением файла pyproject.toml
через PEP 518 (см. Сообщение в блоге автора Б. Кэннона). Инструменты упаковки, такие как " flit
или " poetry
, приняли это современное соглашение для создания дистрибутивов и публикации их на сервере или в индексе пакетов (PyPI). Концепция pyproject.toml
пытается отойти от традиционных файлов setup.py
с особой зависимостью от setuptools
.
зависимости
Такие инструменты, как pipenv
и poetry
имеют уникальный современный подход к решению проблемы зависимостей с помощью файла блокировки. Этот файл позволяет вам отслеживать и воспроизводить состояние ваших графиков зависимостей, что до сих пор было чем-то новым в мире пакетов Python (подробнее о Pipfile и setup.py здесь). Более того, есть утверждения, что вы все еще можете использовать эти инструменты в сочетании с Conda, хотя я не проверял степень этих утверждений. Файл блокировки еще не стандартизирован, но, по словам основного разработчика Б.Кэнона в интервью "Будущее упаковки Python", (~ 33 метра) "Я бы хотел, чтобы мы были там".
Резюме
Если вы работаете с любым пакетом из стека scipy, используйте conda (рекомендуется):
- Для экономии места, времени и проблем с рабочим процессом используйте conda или miniconda.
- Чтобы разрешить развертывание приложений или использование файла блокировки на ваших зависимостях, рассмотрите следующее в сочетании с conda:
-
pipenv
: использовать для развертывания и создания Pipfile.lock
-
poetry
: использовать для развертывания и создания poetry.lock
- Чтобы опубликовать библиотеку на PyPI, подумайте:
-
pipenv
: разработка через pipenv install -e.
и вручную публиковать с помощью шпагата -
flit
: автоматически упаковать и * опубликовать -
poetry
: автоматически упаковывать и публиковать
Смотрите также
Ответ 2
Мне было интересно, если есть подход, чтобы некоторые пакеты, например, те, которые вы используете в большинстве проектов, установлены глобально... Другие вещи будут идти в локальных virtualenv-папках
Да, virtualenv поддерживает это. Установите глобально необходимые пакеты глобально, а затем, всякий раз, когда вы создаете virtualenv, предоставьте --system-site-packages
чтобы получившийся в результате virtualenv мог использовать глобально установленные пакеты. При использовании tox вы можете установить эту опцию в созданных virtualenvs, включив sitepackages=true
в соответствующие [testenv]
.
Ответ 3
Обновленная информация о моем прогрессе:
Менеджер пакетов Conda оказался для меня лучше, чем pipenv по следующим причинам:
- по умолчанию глобальные зависимости доступны в виртуальной среде conda
- это быстрее, чем pipenv при установке/обновлении зависимостей
- объединение pip и conda на самом деле не так проблематично, для всего, где доступен пакет conda, установите с помощью conda, если нет, просто установите с помощью pip
- с помощью
environment.yml
можно за несколько секунд создать заново среду и зависимости для linux и windows - environment.yml позволяет отдельно определять зависимости pip и conda (например, это решает вышеуказанные проблемы с Fiona, Shapely, GDal и т.д.). в Windows, используя версии conda) - conda решает большинство проблем, связанных с поддержкой пакетов/зависимостей на разных платформах (например, linux, mac, win)
- не было проблем с установкой conda (например, miniconda) рядом с независимой установкой Python и использованием conda через
conda run
- если
conda create -n new environment --file requirements.txt
environment.yml отсутствует, то можно создать env из conda create -n new environment --file requirements.txt
)
К сожалению, процесс создания environment.yml
кажется, нигде не описан. Через некоторое время я понял, что автоматически созданный файл (conda env export environment.yml
) необходимо отредактировать вручную, чтобы он содержал наименьший возможный список зависимостей (и пусть conda решит все остальное при установке). В противном случае environment.yml не будет совместим с различными системами.
В любом случае, этот рабочий процесс решает большинство моих проблем, описанных выше, и я счастлив, что мне больше не нужно использовать pipenv или virtualenv.
Есть еще некоторые недостатки,
-
Нужно поддерживать зависимости в нескольких файлах:
- Невозможно выполнить программу напрямую (например, с помощью ярлыка) в ее среде, например, это работает без проблем с
pipenv run
, но: -
conda run
не будет автоматически source activate env
- это открытый вопрос и может быть решен когда-нибудь
- cx_freeze не будет правильно включать глобальные зависимости извне conda env
- С conda будет сложно, если вам нужны зависимости, требующие компиляции (например, C-Extensions и т.д.), см. ниже или здесь
Ответ 4
спасибо за ваш комментарий, я действительно с вами, так как у меня была такая же проблема. Поскольку я сейчас использую PyCharm, он лучше, так как вы можете делать то, что упомянуто из @jwodder выше (и вы также можете использовать pip, bash, vim и т.д. В качестве расширений). Вы можете настроить глобальную среду, а затем установить дополнительные компоненты, необходимые для отдельного проекта. После того, как вы создали свою базовую настройку, она больше не требует постоянной установки... в качестве альтернативы, я бы порекомендовал проверить ваш вариант №. 6) Стихи.ру или токсипы. Было бы здорово, если бы вы могли написать снова, если бы нашли лучшее решение. Привет.