# Python — внешний исполнитель для смарт-скриптов

Python-скриптинг в 1Форме реализован через внешний HTTP-сервис **Python Executor**, на который платформа отправляет код смарт-скрипта. Ниже описаны протокол обмена, настройки подключения, состав передаваемого контекста и отличия Python от остальных языков смарт-скриптов (Lua, JavaScript, OneScript, C#).

## Статус и обзор

**Реализовано.** Python-скриптинг доступен в продакшене с версии 2.268.35. Frontend-редактор поддерживает выбор Python в v2.268.38.

Платформа поддерживает пять языков смарт-скриптов:

| Язык | Движок | `ScriptLanguage` (enum) | `LanguageId` (БД) | Модель исполнения |
|------|--------|-------------------------|-------------------|-------------------|
| Lua | NLua | `Lua = 0` | `0` | Внутри платформы |
| JavaScript | Jint 4.6.0 | `JavaScript = 1` | `1` | Внутри платформы |
| **Python** | **Python Executor (HTTP)** | `Python = 2` | `2` | **Внешний сервис** |
| OneScript | OneScript | `OneScript = 3` | `3` | Внутри платформы |
| C# | Roslyn Scripting 4.12 | `CSharp = 4` | `4` | Внутри платформы |

Ключевое отличие Python от Lua и JavaScript: скрипт исполняется не внутри платформы, а отправляется HTTP-запросом на внешний сервис Python Executor.

---

## Версионирование Python SmartScript — обязательно

Каждый Python SmartScript **обязан** содержать комментарий с версией и датой в начале скрипта. Правило версионирования критично для отладки и отката: без явной версии невозможно определить, какой код выполнялся на момент инцидента.

```python
# v1 | 2026-03-08 15:30 | Начальная версия
# v2 | 2026-03-08 16:45 | Добавлена проверка прав
```

Версия увеличивается при каждом изменении. Соглашение о версионировании единое для всех языков смарт-скриптов — подробнее в разделе [Паттерны JS-скриптов](https://help.1forma.ru/domains/smart-actions/js-jint-patterns.md).

---

## Как платформа выполняет Python-скрипт

Когда смарт-действие запускает скрипт с языком Python, платформа определяет язык скрипта, собирает контекст и отправляет код на внешний сервис Python Executor по HTTP. Результат выполнения возвращается обратно и используется в смарт-действии. Скрипты на остальных языках (Lua, JavaScript, OneScript, C#) платформа выполняет сама, без обращения к внешнему сервису.

## Протокол обмена с Python Executor

**Запрос к Python Executor:**

```
POST {PythonExecutor.ApiUrl}/execute/code
Headers:
  Content-Type: application/json
  X-Api-Key: {ApiKey}   (если настроен)

Body:
{
  "ScriptCode": "def execute(ctx):\n    return ctx['CONTEXT']",
  "Context": { ... },
  "Timeout": 30
}
```

**Ответ** при успешном выполнении:

```json
{
  "Status": "ok",
  "Result": 12345,
  "Output": "debug output...",
  "DurationMs": 42
}
```

**Ответ** при ошибке:

```json
{
  "Status": "error",
  "Error": "NameError: name 'foo' is not defined",
  "Output": "",
  "DurationMs": 5
}
```

**Обработка ошибок.** Платформа прерывает смарт-действие с ошибкой в следующих случаях: сетевая ошибка или таймаут при обращении к сервису; ответ со статусом `error` (текст ошибки берётся из поля `Error`); не задан адрес сервиса (`ApiUrl`).

---

## Контекст скрипта

Python-скрипт получает данные только через объект `ctx`. Платформа собирает контекст и передаёт его в скрипт, отфильтровывая значения по типу:

| Тип значения | Что передаётся |
|-------------|----------------|
| Объекты платформы (задача, пользователь и т.п.) | Только идентификатор (`Id`) |
| Примитивы (строка, число, логическое значение, дата) | Передаются как есть |
| Коллекции (списки, словари) | Только если содержат значения, пригодные для передачи в JSON |
| Сложные объекты | Пропускаются |

### Ключи `ctx`

| Ключ | Тип | Когда присутствует | Значение |
|------|-----|--------------------|----------|
| `DB_TYPE` | `str` | всегда | `MSSQL` или `PG` — тип СУБД площадки |
| `EVENTPARAMS` | `dict` | всегда | параметры события, по которому запущен скрипт; вне события — пустой словарь |
| `EVENTPARAMS_NATIVE` | `list` | если скрипт запущен по событию | те же параметры в исходном виде |
| `CONTEXT` | `int` | если у скрипта задан тип контекста | `Id` контекстного объекта — задачи, пользователя или письма, в зависимости от типа контекста |
| `SESSION_USER` | `int` | если скрипт запущен с контекстом | `Id` пользователя, от имени которого выполняется скрипт |
| `session_user_id` | `int` | то же | дубль `SESSION_USER` |

Ключа `SYSTEM_INFO` (версия платформы и приложение) в Python нет: платформа его формирует, но объект такого типа не сериализуется в JSON и отбрасывается при сборке контекста.

Пример — идентификатор текущей задачи (тип контекста скрипта «Задача»):

```python
def execute(ctx):
    return ctx.get("CONTEXT")
```

Шаблон, который редактор подставляет при создании скрипта на Python, — одна строка `def execute(ctx):`; тело функции дописывается вручную.

---

## Возврат результата и вывод

Результат скрипта определяется двумя способами, приоритет — у первого:

1. Если в скрипте определена функция `execute(ctx)`, платформа вызывает её и берёт возвращённое значение.
2. Иначе результатом становится переменная `result`, если она задана в скрипте.

Вывод `print()` в результат не входит: сервис возвращает вывод и строковое представление результата в поле `Output` ответа, а редактор показывает его в панели вывода (вкладки «Сообщения» и «Результат»).

---

## Конфигурация и Frontend (AdminSPA)

**Настройки подключения к Python Executor** хранятся в настройках сервиса:

| Параметр | Описание |
|----------|----------|
| `ApiUrl` | URL Python Executor (например, `http://python-executor:8000`) |
| `ApiKey` | API-ключ для авторизации (опционально) |

Timeout запроса — 30 секунд. Значение задано константой движка: в отличие от JavaScript и C#, лимит Python настройкой не переопределяется.

**Создание скрипта и выбор языка (AdminSPA).** Язык выбирается при создании скрипта — в диалоге создания автоматизации, поле «Режим редактирования»: Lua, JavaScript, Python, OneScript, C#. В самом редакторе переключателя языка нет: выбранный язык показан в тулбаре текстом, по нему включаются подсветка синтаксиса, расширение при скачивании кода и шаблон новой заготовки (для Python — `def execute(ctx):`).

![Редактор смарт-скрипта в AdminSPA: язык скрипта в тулбаре, кнопки «Выполнить» и «Библиотека», поле кода и история версий](https://help.1forma.ru/help-images/smart-actions/script_editor.png)

---

## Сравнение с Lua/JS

Ключевые отличия Python от языков, выполняемых внутри платформы:

| Аспект | Lua (NLua) | JavaScript (Jint) | Python (Executor) |
|--------|------------|-------------------|-------------------|
| Модель | Внутри платформы | Внутри платформы | Внешний HTTP-сервис |
| Sandbox | Ограниченный | Строгий | Список разрешённых имён и модулей; код исполняется в процессе сервиса |
| Таймаут | 5 мин | 5 мин | 30 сек |
| API-объекты платформы (SQL, SMART, CACHE, REGISTRY, FILES) | Доступны | Доступны | **Недоступны** — только данные из `ctx` |
| Внешний HTTP | Доступен | Доступен | Доступен через `requests` / `httpx` |
| Библиотеки (include) | Да | Да | Нет |
| Возврат результата | `RESULT = value` | `RESULT = value` | `return` из `execute(ctx)` либо переменная `result` |
| Зависимости | NLua + Lua DLL | Нет (pure .NET) | Python Executor (Docker) |

**Ограничения Python:** объекты API платформы недоступны — SQL, SMART, CACHE, REGISTRY, FILES и платформенная обёртка над HTTP. Скрипт оперирует данными из контекста и стандартной библиотекой Python; внешний HTTP-вызов возможен напрямую сетевой библиотекой (`requests`, `httpx`), а обращение к БД — нет. Для работы с БД и смарт-действиями рекомендуются Lua или JavaScript.

Состав песочницы и полный перечень доступных из скрипта модулей описаны в документации самого сервиса. Пакеты, установленные в образе, и пакеты, разрешённые скрипту, — разные списки: часть библиотек нужна только внутренним обработчикам сервиса и из смарт-скрипта недоступна.

---

## Связанные документы домена Smart Actions

Документация по другим языкам смарт-скриптов:

- [JavaScript в смарт-скриптах (Jint)](https://help.1forma.ru/domains/smart-actions/js-scripting-jint.md) — выполнение внутри платформы, изоляция, доступные API-объекты
- [C# в смарт-скриптах (Roslyn)](https://help.1forma.ru/domains/smart-actions/csharp-scripting-roslyn.md) — компиляция и выполнение C#-кода
- [Обработка ошибок Lua (pcall)](https://help.1forma.ru/domains/smart-actions/faq-lua-pcall-error-handling.md) — особенности NLua, обработка ошибок
