# Python : переменные


## Переопределяемые переменные { #D }

Переменные, которые можно переопределить из командной строки [`ya make -DVAR`](../../usage/ya_make/index.md#D)

### USE_SYSTEM_PYTHON

Наша сборка стремится быть герметичной и воспроизводимой. Поэтому использовать в сборке инструменты с локальной системы (включая Python) не самая лучшая идея. Однако,
иногда необходимо собрать код с использованием обычного (не Аркадийного) пакета Python, причём определённой версии. Это не работает для [аркадийной сборки Python](index.md#arcadia_python),
но необходимо для сборки [расширений для внешнего Python](index.md#py_modules). Чтобы собрать код с использованием обычного Python, надо подать в командную строку `ya make` определение
переменной `USE_SYSTEM_PYTHON` с указанием версии.

**Пример:**
```
[=] ya make -DUSE_SYSTEM_PYTHON=3.7 devtools/dummy_arcadia/test/system_python
```

При этом пакет с необходимым Python будет загружен из Sandbox как ресурс и будет использован при сборке. Например, из него будет взят заголовочный файл `Python.h`.

Доступные версии Python описаны в настройках системы сборки и могут быть найдены [таким запросом](https://a.yandex-team.ru/search?search=select%20%5C%28%5C%24USE_SYSTEM_PYTHON%5C%29,%5E.*,j,arcadia,,5000).
Ниже найденной строки располагается конструкция, которая выглядит так:
```
    select ($USE_SYSTEM_PYTHON) {
        "2.7" ? {
            _SYSTEM_PYTHON27=yes
            PY_VERSION=2.7
            PY_FRAMEWORK_VERSION=2.7
        }
        "3.4" ? {
            _SYSTEM_PYTHON34=yes
            PY_VERSION=3.4m
    ...
```
Не очень важно понимать, что делает этот код, достаточно посмотреть на значения перед `?` -- это и есть доступные версии.


{% note alert %}

Никогда не собирайте `PY*_LIBRARY` и `PY*_PROGRAM` с `USE_SYSTEM_PYTHON` -- ничего хорошего из этого не выйдет. Даже если сборка завершится успехом, получившейся код будет неработоспособен.

{% endnote %}


### USE_ARCADIA_PYTHON

Аркадия также позволяет использовать при сборке Python, указанный пользователем. Это негерметичный и небезопасный способ сборки, поэтому он не рекомендуется к использованию.
Включается он указанием переменной `USE_ARCADIA_PYTHON=no` в командной строке `ya make`.

**Пример:**
```
[=] ya make -DUSE_ARCADIA_PYTHON=no -DOS_SDK=local devtools/dummy_arcadia/test/system_python
```

{% note info %}

Локальный Python может быть несовместим SDK привозимым в Аркадийную сборку, поэтому обязательно указывать `-DOS_SDK=local` для использования SDK тоже с локальной системы.

{% endnote %}

Сборка c `-DUSE_ARCADIA_PYTHON=no` пытается сконфигурировать Python, установленный в системе. Будут использованы исполняемые файлы `python` и `python-config`, найденные в `$PATH`. 
Их можно переопределить сборочными флагами `PYTHON_BIN` и `PYTHON_CONFIG` соответственно.

Флаги, полученные от python-config, можно переопределить отдельно:

Переменная | Описание | Пример
:--- | :--- | :---
`PYTHON_BIN` | размещение программы `python` | `/usr/local/bin/python`
`PYTHON_CONFIG` | размещение программы `python-config` | `/usr/local/bin/python-config`
`PYTHON_FLAGS` | флаги компилятора | `-fno-strict-aliasing -fstack-protector`
`PYTHON_LDFLAGS` | флаги компоновщика | `-L/usr/lib/python2.7/config`
`PYTHON_LIBRARIES` | дополнительные библиотеки при компоновке | `-lpthread` 
`PYTHON_INCLUDE` | флаги компилятора, указывающие директории для поиска `#include` | `-I/usr/include/python2.7`

Если `python` или `python-config` не были найдены или при запуске `python-config` не удалось получить список флагов, `Python` считается не полностью сконфигурированным.
Сейчас все его опции в командах сборки будут заменены на строку `PYTHON-NOT-FOUND`, в будущем, возможно, это будет ошибка конфигурации.
В этом случае нужно явно указать правильные `PYTHON_BIN`  и `PYTHON_CONFIG`. Вместо последнего можно явно указать все 4 флага `PYTHON_FLAGS`,  `PYTHON_LDFLAGS`, `PYTHON_LIBRARIES`  и  `PYTHON_INCLUDE`.


{% note alert %}

Мы не рекомендуем использовать сборку с пользовательским Python в production и её поддержка у нас ограничена: сборка может быть сломана без предупреждения или не работать в некоторых конфигурациях,
и мы не гарантируем, что будем решать все проблемы, возникающие в ходе её использования. Если для вас требуются дополнительные гарантии, о них нужно договариваться отдельно.

{% endnote %}



## Переменные для ya.make

### PYTHON2/PYTHON3 { #py_ver }

При написании Python2/3 совместимого кода иногда необходимо модифицировать сборку в зависимости от версии питона, для которой собирается Pyhton2/3 мультимодуль.

Для этого можно использовать переменные `PYTHON2` и `PYTHON3`, установленные при сборке под Python2 и Python3 соответственно.

Переменные работают во всех мультимодулях, чувствительных к версии Python, например в [`PY23_LIBRARY`](modules.md#py23_library), `PROTO_LIBRARY`

**Пример:**
```
IF (PYTHON2)
    PEERDIR(contrib/python/six)
ENDIF()
```

## Переменные окружения

### Y_PYTHON_ENTRY_POINT

Через переменную окружения `Y_PYTHON_ENTRY_POINT=module.path:func_name` можно заменить точку входа в Python-программе на произвольную функцию.
Это может быть полезно для ручного тестирования и отладки на уровне функций.

- `Y_PYTHON_ENTRY_POINT=path.to.package:myfunc ./your_program` запустит `myfunc`  в пакете `path.to.package`. Неприятный участок можно поместить внутрь в `try: ... except: type, value, tb = sys.exc_info(); traceback.print_exc(); pdb.post_mortem(tb)`, чтобы провалиться в pdb как в следующем способе.

В стандартной библиотеке в этой роли полезны `code:interact` и `pdb:set_trace`, в программах, собранных с `contrib/python/ipython` — `IPython:start_ipython`.

В [модуле по умолчанию](https://a.yandex-team.ru/arc/trunk/arcadia/library/python/runtime/entry_points.py):

- `:repl` — запускает `IPython:start_ipython` или `code:interact`, помещая в пространство имён интерпретатора всё, что определено в модуле, указанном в `PY_MAIN`. В результате запуск провалится в консоль IPython, и в ней можно будет в интерактивном режиме вызывать функции из кода Python-программы и её модулей.

В [main.c](https://a.yandex-team.ru/arc/trunk/arcadia/library/python/runtime/main/main.c?rev=2957993):

- `:main` — запускает main интерпретатора (`Py_Main`). Например, `Y_PYTHON_ENTRY_POINT=:main ./your_program my_script.py` запустит скрипт `my_script.py`.

### Y_PYTHON_SOURCE_ROOT

При наличии `Y_PYTHON_SOURCE_ROOT=/path/to/source/root` Python-программы, собранные в Аркадии, импортируют встроенные в них модули не из себя ([как диктует аркадийная сборка](modules.md#python_program)), а с файловой системы, если находят их исходники относительно заданной директории.
Благодаря этому во время разработки можно не пересобирать приложение, когда меняются только .py файлы.

Без этой переменной аттрибут `__file__` модулей содержит путь к файлу относительно корня аркадии. Эта переменная добавляется в начало `__file__` и делает путь абсолютным.

{% note alert %}

Не распространяйте действие этой переменной на всю систему (e.g. через `.bashrc`), так как это нарушит работу `ya` и других аркадийный приложений на Python,
когда репозиторий отличается от приложения более чем правкой `.py` файлов.

{% endnote %}

Чтобы обобщить такой запуск на все разрабатываемые вами приложения, можно запускать их через alias/function/wrapper. Например, [dev](https://a.yandex-team.ru/arc/trunk/arcadia/junk/orivej/skel/bin/dev/?rev=5197704) и [idev](https://a.yandex-team.ru/arc/trunk/arcadia/junk/orivej/skel/bin/idev/?rev=2787117).

### Y_PYTHON_EXTENDED_SOURCE_SEARCH

Если `Y_PYTHON_EXTENDED_SOURCE_SEARCH` содержит произвольное непустое значение и установлена переменная `Y_PYTHON_SOURCE_ROOT`, то включается расширенный режим поиска исходных файлов. В этом режиме используется отображение имен пакетов (python package) на каталоги, в которых находятся модули этих пакетов. Это позволяет импортировать модули, которых не существовало на момент компиляции приложения, что уменьшает количество ситуаций, требующих запуска `ya make`. Переменная работает только для Python 3.
