Разделение зависимостей для локальной разработки и рабочего сервера (pip, requirements.txt)

Имеем

  • Локальный проект, локальное виртуальное пространство
  • Git репозиторий
  • Рабочий проект (сервер), рабочее виртуальное пространство

Для создания зависимостей очень удобно использовать pip freeze > requirements.txt на локалке. Через git закинул на рабочий сервер, а далее установил все зависимости.

Но сейчас решил потестировать различные модули и в локальное виртуальное пространство установил кучу python'ских пакетов, которые обязательно попадут в requirements.txt, а затем в рабочее окружение. В действительности они там не нужны.

Есть ли готовое решения для управления двумя версиями зависимостей? Один для рабочего окружения, другой для локального использования. Может какой нибудь менеджер существует?


Ответы (3 шт):

Автор решения: Roman Konoval

Вот один вариант разделения и наследования зависимостей, через включение файлов зависимостей.

Создаете файл runtime-requirements.txt с зависимостями для прода.

Для локальной разработки создаете dev-requirements.txt и туда в дополнение к зависимостям используемым чисто для разработки включаете строку:

-r runtime-requirements.txt

Она заставит pip включить все зависимости из runtime-requirements.txt при выполнении pip install -r dev-requirements.txt.

Оба файла хранятся в git, и меняются хоть вручную, хоть с помощью pip freeze при добавлении новых зависимостей.

Обычно я использую даже три файла: runtime.txt -> test.txt -> dev.txt.

test.txt - для использования на CI (всякие Hamcrest, testcontainers, factoryboy и прочее). dev.txt - ipdb, django-debug-toolbar и т.п.

→ Ссылка
Автор решения: Evgeniy Blinov

Как вариант, можно устанавливать зависимости прямо в рантайме. У меня есть библиотечка для этого.

Устанавливается так:

pip install instld

Когда она уже установлена, можно прямо в рантайме поставить любую библиотеку:

import installed

with installed('some_package') as context:
  import some_module

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

В случае использования данной библиотеки вы можете передавать ожидаемые версии зависимостей в виде переменных среды.

→ Ссылка
Автор решения: insolor

Как упомянули в комментариях, можно использовать poetry.

Вместо отдельных файлов зависимостей там используется общий файл проекта pyproject.toml, в котором могут быть отдельные разделы (группы) для обязательных зависимостей (для "боевого" окружения) и, например, для разработки. Раньше было разделение только на боевые/"разработческие" зависимости, сейчас можно создавать в принципе неограниченное количество групп.

Пример:

> poetry new test-project  # Создаем новый пустой проект
Created package test_project in test-project
> cd test-project
> ls
pyproject.toml  README.md  test_project  tests
> poetry add requests  # Добавляем "боевую зависимость"
> poetry add --group dev black # Добавляем "девелоперскую" зависимость
> poetry add --dev black # То же самое, но в стиле более старых версий poetry (напишет, что этот вариант deprecated)
> poetry add --group test pytest # Добавляем зависимость для тестирования

Для инициализации pyproject.toml в уже существующем проекте вместо poetry new нужно использовать poetry init.

Смотрим pyproject.toml:

[tool.poetry]
name = "test-project"
version = "0.1.0"
description = ""
authors = ["user <[email protected]>"]
readme = "README.md"
packages = [{include = "test_project"}]

[tool.poetry.dependencies]
python = "^3.10"
requests = "^2.29.0"


[tool.poetry.group.dev.dependencies]
black = "^23.3.0"


[tool.poetry.group.test.dependencies]
pytest = "^7.3.1"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

Локально когда вы добавили первую зависимость вам автоматом создало виртуальное окружение и установило зависимость туда.

Удаление зависимостей - через команду poetry remove .... Можно править и файл pyproject.toml, но после изменений нужно выполнять команду poetry update, чтобы зависимости установились/удалились.

Дальше, если вы только выкачали проект с github, и хотите создать виртуальное окружение с установкой всех зависимостей, выполняете команду (установятся все группы зависимостей, кроме обозначенных необязательными):

poetry install

Если нужны только основные ("боевые") зависимости, вместо этого нужно выполнить команду

poetry install --only-root

Если нужно установить только основные и тестовые зависимости (но не нужны всякие форматтеры), нужна команда

poetry install --with test

Документация по управлению зависимостями: Managing dependencies


Ну и в целом как работать с poetry:

poetry run python some_script.py

- запустит команду в виртуальном окружении, но без постоянной активации виртуального окружения.

Это удобно, например, для запуска команд из окружения в CI:

    - name: Test with pytest
      run: |
        poetry run pytest --cov=./

Аналог активации виртуального окружения как при работе с venv/virtualenv выполняется командой

poetry shell

Деактивация окружения - командой exit (без poetry).

→ Ссылка