# ya ide venv : создание виртуального окружения Python

Задачи, решаемые виртуальным окружением:
1. Облегчает разработку и отладку проектов на Python тем разработчикам, которые используют [аркадийную сборку](https://docs.yandex-team.ru/ya-make/manual/python/).
2. Полезен командам, которые не занимаются дистрибуцией кода на Python, но нуждаются в коде из Аркадии. Им становятся доступны, как аркадийные библиотеки, так и внешние, устанавливаемым пакетным менеджером pip.

{% note warning %}

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

{% endnote %}

### Создание venv

```bash
ya ide venv {VENV_OPTIONS} [YA_MAKE_OPTIONS] [TARGET ...]
```

**Поддерживаемые флаги**:
- `--venv-root={path}` - каталог, в котором будет создано виртуальное окружение. Если каталог не существует, он будет создан.
Если в каталоге уже есть виртуальное окружение, оно будет обновлено.
- `--venv-with-pip` - установить pip в созданное виртуальное окружение.
- `--venv-add-tests` - в собираемый интерпретатор включить проекты с тестами. Пока можно запускать только те тесты, которые не требуют аркадийного окружения (`DEPENDS`, `DATA`, рецепты, канонизация) и не используют библиотеку `yatest`.
- `--venv-tmp-project={name}` - имя временного проекта в junk-каталоге пользователя. По умолчанию - `_ya_venv`. Проект нужен только на время компиляции Python-интерпретатора, по завершении который проект автоматически удаляется.
- `--venv-excluded-peerdirs={peerdir}` - из сборки виртуального окружения полностью убрать аркадийную версию указанной библиотеки (и её зависимости, если они вне неё нигде не используются). Флаг можно указывать несколько раз, если нужно исключить больше одной библиотеки. Фильтрация производится по точному соответствию, то есть указание `--venv-excluded-peerdirs=contrib/lib` *не означает*, что будет отфильтрована и `contrib/lib/sublib`.

Кроме флагов `venv` можно применять большинство флагов `ya make`.
Если не нужно отлаживать интерпретатор или нативную библиотеку в его составе, лучше использовать релизную сборку, то есть добавлять флаг `-r`.

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

В результате выполнения команды в каталоге, указанном во флаге `--venv-root`, создаётся виртуальное окружение, где в качестве интерпретатора установлен аркадийный Python. Он содержит в себе все нативные библиотеки, сгенерированные py-файлы и ресурсы, необходимые для выполнения кода, указанного в `TARGET`. Исходные файлы Python (*.py), которые лежат в Аркадии в готовом виде (включая стандартную библиотеку), в интерпретатор не добавляются. Интерпретатор загружает их напрямую из Аркадии. Путь к корню Аркадии сохраняется в `pyvenv.cfg` в процессе создания окружения, поэтому установка переменной окружения [Y_PYTHON_SOURCE_ROOT](https://docs.yandex-team.ru/ya-make/manual/python/vars#y_python_source_root) не требуется.

При использовании макроса `RESOURCE_FILES` и API, которые описаны на [wiki](https://wiki.yandex-team.ru/devtools/commandsandvars/resourcefiles/), загрузка соответствующих ресурсов также производится из Аркадии.

Макросы сборки `TOP_LEVEL` и `NAMESPACE` меняют связь между полным именем модуля и его расположением в файловой системе, поэтому аркадийный Python содержит систему импорта, которая поддерживает эти макросы. Специально для venv эта система доработана: вместо хранения соответствия каждого модуля файлу в Аркадии, этот словарь расширен до уровня пакетов, где для каждого пакета хранится перечень каталогов, в которых нужно искать модули пакета. Это, с одной стороны, позволяет не пересобирать интерпретатор после добавления новых файлов, но может привести к неожиданному поведению, если в проекте есть разные файлы с совпадающими полными именами модулей.


**Когда нужно повторно запускать ya ide venv**:
- если в проект через PEERDIR добавилась новая ранее не используемая зависимость;
- если произошли изменения в библиотеке с нативным кодом, protobuf- или flatbuf-библиотеке, в общем всегда, когда затронуты сущности, загружаемые из интерпретатора, а не из файловой системы;
- в существующем проекте поменяли NAMESPACE.
- в дерево проектов добавили новый проект.

**Пакетный менеджер pip и внешние зависимости**

Если окружение создано с флагом `--venv-with-pip`, то после первичной настройки в него скачивается и устанавливается последняя версия пакетного менеджера `pip`.
Установленные в окружение пакеты имеют приоритет над аркадийными (но см. примечание ниже).

После повторного запуска `ya ide venv` ранее установленные модули сохраняются.

{% note alert %}

Приоритет пакетов из venv над аркадийными корректно работает только для pure-Python библиотек. Для нативных библиотек конфликт имён приводит к непредсказуемому поведению и аварийному завершению интерпретатора, поэтому такие библиотеки лучше полностью исключать из сборки с помощью флага `--venv-excluded-peerdirs`.

{% endnote %}
