Ад зависимости Python: компромисс между virtualenv и глобальными зависимостями?

До сих пор я тестировал различные способы управления зависимостями моего проекта в Python:

  1. Установка всего глобального с помощью pip (экономит место, но рано или поздно доставляет вам неприятности)
  2. pip & venv или virtualenv (немного мучительно, но во многих случаях это нормально)
  3. pipenv & pipfile (немного проще, чем venv/virtualenv, но медленный и некоторые блокировщики, виртуальные envs прячутся где-то еще, чем папка реального проекта)
  4. conda в качестве менеджера пакетов и среды (отлично, если все пакеты доступны в conda, смешивать pip & conda немного смешно)
  5. Поэзия - я не пробовал этот
  6. ...

Моя проблема со всем этим (кроме 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.

Есть еще некоторые недостатки,

  1. Нужно поддерживать зависимости в нескольких файлах:

    • setup.py
    • environment.yml
  2. Невозможно выполнить программу напрямую (например, с помощью ярлыка) в ее среде, например, это работает без проблем с pipenv run, но:
    • conda run не будет автоматически source activate env
    • это открытый вопрос и может быть решен когда-нибудь
  3. cx_freeze не будет правильно включать глобальные зависимости извне conda env
  4. С conda будет сложно, если вам нужны зависимости, требующие компиляции (например, C-Extensions и т.д.), см. ниже или здесь

Ответ 4

спасибо за ваш комментарий, я действительно с вами, так как у меня была такая же проблема. Поскольку я сейчас использую PyCharm, он лучше, так как вы можете делать то, что упомянуто из @jwodder выше (и вы также можете использовать pip, bash, vim и т.д. В качестве расширений). Вы можете настроить глобальную среду, а затем установить дополнительные компоненты, необходимые для отдельного проекта. После того, как вы создали свою базовую настройку, она больше не требует постоянной установки... в качестве альтернативы, я бы порекомендовал проверить ваш вариант №. 6) Стихи.ру или токсипы. Было бы здорово, если бы вы могли написать снова, если бы нашли лучшее решение. Привет.