Настройка проекта Python — виртуальные среды и управление пакетами

Виртуальные среды в Python

Виртуальные среды - это изолированные среды Python, которые имеют свои собственные site-packages. По сути, это означает, что каждая виртуальная среда имеет свой собственный набор зависимостей от сторонних пакетов, обычно устанавливаемых из PyPI.

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

Сегодня мы будем учиться

  • какие инструменты существуют для создания изолированных сред
  • какие инструменты помогают в управлении пакетами в проектах Python

Создание виртуальных сред

В экосистеме Python существует два распространенных способа создания виртуальных сред: virtualenv и venv.

venv

venv является, вероятно, самым популярным выбором для создания виртуальных сред в Python. Начиная с Python 3.3 venv является частью стандартной библиотеки и поэтому обычно доступен, когда у вас установлен Python. Однако дистрибутивы Linux на базе Debian требуют установки python3-venv, поскольку их сопровождающие решили отделить этот модуль от основной установки Python.

Для создания виртуальной среды с помощью venv можно начать с ввода

python -m venv venv

Эта команда создает каталог под названием venv внутри вашей текущей папки. Теперь, чтобы использовать эту новую виртуальную среду, вы должны активировать ее с помощью этой команды:

source venv/bin/activate # Use this command on bash
.\venv\Scripts\activate # On Windows

Теперь вы можете запустить интерпретатор Python и набрать

>>> import sys
>>> sys.executable
'/Users/bas/Code/tmp/venv/bin/python'
>>> for path in sys.path:
...     print(repr(path))
...
''
'/usr/local/Cellar/python@3.9/3.9.6/Frameworks/Python.framework/Versions/3.9/lib/python39.zip'
'/usr/local/Cellar/python@3.9/3.9.6/Frameworks/Python.framework/Versions/3.9/lib/python3.9'
'/usr/local/Cellar/python@3.9/3.9.6/Frameworks/Python.framework/Versions/3.9/lib/python3.9/lib-dynload'
'/Users/bas/Code/tmp2/venv/lib/python3.9/site-packages'
>>>

Как видите, интерпретатор Python, который вы только что запустили, находится внутри вашей виртуальной среды. Кроме того, каталог site-packages (где находятся установленные пакеты pip) указывает на путь внутри вашей виртуальной среды.

virtualenv

virtualenv работает аналогично. Чтобы использовать его, вы должны сначала установить его через pip:

pip install virtualenv

Затем вы можете использовать его с

python -m virtualenv venv

Обратите внимание, что мы только что изменили имя модуля с venv на virtualenv (первый аргумент). Папка назначения venv остается нетронутой. virtualenv создаст такую же структуру каталогов, как и venv ранее. Активировать новую виртуальную среду нужно точно так же, как и раньше:

source venv/bin/activate # On bash

virtualenv против venv

Вам может быть интересно, в чем разница между этими двумя инструментами.

Во-первых, virtualenv имеет более долгую историю. Он использовался уже во времена Python 2. Официальная поддержка виртуальных сред была добавлена в Python не ранее версии 3.3 через PEP 405.

Как пакет стороннего разработчика, virtualenv имеет дополнительное преимущество: он не зависит от установки Python в системе и поэтому может быть обновлен независимо.

Однако самое важное преимущество использования virtualenv вместо venv заключается в том, что это позволяет использовать версии Python, отличные от системного Python. Если у вас установлен только Python 3.9, вы можете использовать virtualenv для создания виртуальной среды с Python 3.10 (и наоборот, конечно). Вы не только можете использовать любую поддерживаемую версию Python, но и делать это без разрешений root или Administrator, поскольку установка выполняется внутри вашего рабочего каталога.

С другой стороны, виртуальные среды, созданные с помощью virtualenv, сложнее. Это связано с тем, что кросс-Python поддержка (даже Python 2 все еще поддерживается) делает открытие пакетов и внутренних компонентов немного сложнее, а процесс загрузки необходимо настраивать. Если вас интересуют эти внутренние аспекты, в докладе Берната Габора EuroPython 2019 эти вопросы освещены.

Подведем итоги:

  venv virtualenv
Хорошо
  • "Официальный" способ создания виртуальных сред
  • Более чистая структура каталогов
  • Поддерживает различные версии Python
  • Независимость от системы Python
  • Двухлетний льготный период для устаревших версий Python
Плохо
  • медленнее, чем virtualenv
  • Более подвержен ошибкам, так как виртуальная среда более сложная

Установка пакетов

Теперь, когда у нас есть рабочая виртуальная среда с virtualenv или venv, мы можем начать установку пакетов, необходимых для выполнения зависимостей нашего проекта.

pip

pip является стандартом де-факто для установки пакетов в Python и является частью стандартной библиотеки с версии Python 3.4.

Чтобы установить пакет, вы можете просто ввести

pip install django

pip позаботится о поиске пакета на PyPI и управлении его зависимостями. В нашем примере мы можем проверить, какие пакеты были установлены с помощью команды выше:

$ pip list
Package    Version
---------- -------
asgiref    3.5.0
Django     4.0.2
pip        21.1.3
setuptools 57.0.0
sqlparse   0.4.2

Как видите, помимо Django, pip установил asgiref и sqlparse.

Наиболее распространенным способом совместного использования среды, созданной с помощью pip, является создание файла requirements.txt, который выглядит следующим образом:

django==4.0.2

Проблема с pip заключается в том, что он заботится об установке зависимостей, но не заботится о них после. Так, например, если вы установите django вместе с pip, он установит sqlparse и asgiref за вас. Однако, если после этого вы удалите django, эти два дополнительных пакета сохранятся и не будут удалены. Со временем вы можете потерять представление о том, какие пакеты действительно необходимы для вашего проекта, а какие являются просто остатками ранее установленных пакетов. Эта ситуация особенно актуальна, когда вы мигрируете с одного модуля PyPI на другой в течение жизни вашего проекта.

pip также не делает различий между средой разработки и производственной средой. Так, вы можете захотеть иметь доступ к инструментам разработчика, таким как black или pytest во время разработки. Установка таких инструментов на рабочем сервере в лучшем случае не нужна, а в худшем - вредна.

Кроме того, когда два сторонних пакета имеют сталкивающиеся зависимости, pip не предоставляет способа их устранения.

И последнее, об управлении вашей requirements.txt не позаботится pip. Некоторые разработчики просто используют pip freeze > requirements.txt всякий раз, когда установлена новая зависимость. Однако это не рекомендуется, так как в этом случае будут включены подзависимости, что усугубит вышеупомянутые проблемы.

pipenv

pipenv - это инструмент, созданный Кеннетом Рейтцем. Наиболее существенным отличием от pip является то, что pipenv предназначен для автоматического отслеживания установленных пакетов. Для этого pipenv создает два файла, Pipfile и Pipfile.lock.

pipenv решает проблемы с pip, упомянутые выше:

Управление зависимостями

Установка пакета автоматически обновляет Pipfile и Pipfile.lock

Когда мы устанавливаем django с pipenv, он установит sqlparse и asgiref за нас, как это сделал бы pip. Однако, если мы удалим django из наших требований, pipenv удалит и эти дополнительные зависимости.

Зависимости производства/разработки

Некоторые зависимости, такие как линтеры или инструменты тестирования, необходимы только в среде разработки. Поэтому pipenv поддерживает флаг --dev. Пакеты, установленные с этим флагом, не устанавливаются при тиражировании среды на производственные системы.

Виртуальные среды

pipenv также может создавать и управлять виртуальными средами для вас. На практике это означает, что вы можете полагаться исключительно на pipenv для создания окружения вашего проекта, включая установку указанных версий Python.

По команде

pipenv --python 3.10

вы можете легко создать совершенно новый виртуальный env с указанной версией Python.

poetry

poetry - это новый и очень амбициозный менеджер пакетов для Python. Его цель - обеспечить решение всех проблем виртуального окружения и управления пакетами, с которыми может столкнуться разработчик.

Интересно, что poetry - в отличие от pipenv - не является "официальным" пакетом под эгидой Python Packaging Authority. Однако он полагается на файл под названием pyproject.toml (вместо Pipfile и Pipfile.lock, как это делает pipenv). Спецификация pyproject.toml имеет "официальный статус" согласно PEP 518.

Также poetry можно использовать для управления виртуальными средами и пакетами, создания и публикации собственных пакетов Python.

pyproject.toml

poetry опирается на файл pyproject.toml, который выглядит следующим образом:

[tool.poetry]
name = "poetry_tutorial_project"
# ...

[tool.poetry.dependencies]
python = "^3.10"
loguru = "*"
psutil = "*"

[tool.poetry.dev-dependencies]
pytest = "*"

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

[tool.poetry.scripts]
run = "wsgi:main"

Этот файл является единственным конфигурационным файлом, который использует poetry и содержит всю информацию о зависимостях, инструкциях по сборке и тестовых средах.

Виртуальные среды и создание скелета

Команда poetry new projectname создает для вас разумную структуру проекта:

/projectname
├── README.md
├── projectname
│   └── __init__.py
├── pyproject.toml
└── tests
    ├── __init__.py
    └── test_projectname.py

Зависимости могут быть добавлены с помощью

poetry add django

--dev-dependency может использоваться для добавления зависимости только для среды разработки.

Создать и опубликовать

poetry также может позаботиться о сборке и публикации ваших пакетов в PyPI. В этом смысле он заменяет twine. Вот хорошее руководство по использованию poetry для упаковки проектов Python.

pip против pipenv против poetry

  pip pipenv poetry
Хорошо
  • Пожалуй, наиболее часто используемый инсталлятор пакетов
  • Прост в использовании и включен в стандартную библиотеку
  • Официальный проект PyPA
  • Управляет зависимостями, также при деинсталляции пакетов
  • Создание виртуальных сред
  • использует официальный pyproject.toml стандарт
  • Создание виртуальных сред
  • Может использоваться для сборки и публикации пакетов
  • Создает структуру проекта
Плохо
  • Нет воспроизводимого управления зависимостями
  • Документирование зависимостей - это ручной процесс (requirements.txt)
  • Отсутствует поддержка pyproject.toml файлов
  • Большой объем проекта: не один инструмент для работы (может также рассматриваться как преимущество)

Другие инструменты, о которых стоит упомянуть

virtualenvwrapper

virtualenvwrapper - это множество расширений virtualenv.

В пакет входит несколько удобных утилит CLI. Наиболее важные из них:

  • mkvirtualenv: Ярлык для создания виртуальной среды. В отличие от venv и virtualenv, виртуальные среды, создаваемые virtualenvwrapper, помещаются не в рабочий каталог, а в центральный каталог вашего каталога $HOME. Виртуальное окружение создается командой mkvirtualenv projectenv.
  • workon: Поскольку virtualenvwrapper создает виртуальные среды в центральном каталоге, активация выполняется командой workon. Независимо от того, каков ваш текущий рабочий каталог, вы можете выполнить команду workon projectenv, которая автоматически выберет нужное окружение из вашего каталога $HOME и активирует его.

pyenv

pyenv - это инструмент для управления версиями Python. Кроме инструментов, которые мы обсуждали до сих пор, он не помогает ни в управлении виртуальными средами, ни в управлении пакетами. Однако pyenv, конечно же, совместим с другими инструментами. pyenv может быть удобным помощником для организации рабочих мест разработчиков. Сам по себе он не зависит от Python, поэтому его можно использовать для настройки различных установок Python удобно и без root / Administrator прав.

Чтобы установить определенную версию Python, введите:

pyenv install 3.10

Для использования pyenv в сочетании с менеджерами виртуальных сред, команда pyenv создала некоторые плагины:

Утратил силу: pyvenv

pyvenv (не путать с pyenv) - это скрипт для создания виртуальных сред, который раньше поставлялся с Python 3. Начиная с версии Python 3.6 он был устаревшим и заменен на python -m venv.

CLI

Иногда вы просто хотите использовать инструмент CLI от PyPI. В этом случае вам не нужна виртуальная среда для целей разработки, а только для управления вашими инструментами CLI. Различные инструменты CLI, которые вы используете каждый день, имеют свои собственные зависимости, поэтому установка этих инструментов в системе Python может снова привести к известным проблемам. Таким образом, имеет смысл создать для каждого CLI-инструмента отдельную виртуальную среду.

Чтобы сделать этот процесс удобным и управляемым, существуют инструменты, которые делают именно это: создают изолированную среду для инструментов CLI, а затем запускают эти инструменты CLI.

pipx

С помощью pipx вы можете установить пакет, который раскрывает сценарий CLI. pipx автоматически создаст отдельную виртуальную среду для каждого инструмента CLI и поместит симлинк на каталог под названием .local/bin внутри вашего каталога $HOME.

Чтобы установить инструмент CLI из PyPI, просто введите:

$ pipx install pycowsay
  installed package pycowsay 0.0.0.1, Python 3.9.6
  These apps are now globally available
    - pycowsay
done! ✨ 🌟 ✨

Когда он установлен, вы волшебным образом получаете инструмент CLI, доступный в вашей оболочке, и он не загрязняет пакеты Python вашей системы.

$ pycowsay bas.codes

  ---------
< bas.codes >
  ---------
   \   ^__^
    \  (oo)\_______
       (__)\       )\/\
           ||----w |
           ||     ||

pip-run

pip-run служит той же цели, что и pipx. Единственное отличие состоит в том, что pip-run не обеспечивает постоянную установку пакета, а удаляет все среды после запуска инструмента.

$ pip-run -q pycowsay -- -m pycowsay "bas.codes"


  ---------
< bas.codes >
  ---------
   \   ^__^
    \  (oo)\_______
       (__)\       )\/\
           ||----w |
           ||     ||

Если вы просто хотите попробовать пакет, pip-run является отличным инструментом, так как он делает очистку за вас. Вы даже можете запустить интерактивный интерпретатор с установленным пакетом, что делает pip-run полезным не только для инструментов CLI, но и для исследования пакетов модулей из PyPI:

$ python -m pip-run -q boto
>>> import boto

https://bas.codes/posts/python-virtualenv-venv-pip-pyenv-poetry

Вернуться на верх