
Легковесная кроссплатформенная изоляция процессов на основе среды выполнения OpenAI Codex. Изолируйте любую команду с контролем файлов, сети и учетных данных.
Python SDK для zerobox. Изолируйте любую команду с помощью управления файлами, сетью и учётными данными.
pip install zerobox
Установка wheel-пакета добавляет CLI zerobox в bin/ вашего окружения и предоставляет Python SDK.
Об использовании CLI, концепциях секретов, полном справочнике флагов, показателях производительности и поддерживаемых платформах см. основной README.
from zerobox import Sandbox
sandbox = Sandbox.create({"allow_write": ["/tmp"]})
print(sandbox.sh("echo hello").text())
Три способа запустить команду. Каждый возвращает ShellCommand, который вы завершаете с помощью .text(), .json() или .output().
name = "world"
sandbox.sh(f"echo hello {name}").text()
data = sandbox.py("import json; print(json.dumps({'sum': 1 + 2}))").json()
sandbox.exec("python3", ["-c", "print('hi')"]).text()
| Метод | При успехе | При ненулевом коде выхода |
|---|---|---|
.text() | Возвращает stdout в виде строки | Вызывает SandboxCommandError |
.json() | Разбирает stdout как JSON | Вызывает SandboxCommandError |
.output() | Возвращает CommandOutput(code, stdout, stderr) | Возвращает ту же структуру, никогда не вызывает исключение |
data = sandbox.sh("cat data.json").json()
result = sandbox.sh("exit 42").output()
# CommandOutput(code=42, stdout='', stderr='')
Используйте AsyncSandbox в асинхронных приложениях, чтобы ожидание работы изолированного подпроцесса
не блокировало цикл событий. Форма команды такая же, как у Sandbox, но
создание и терминаторы ожидаются через await.
from zerobox import AsyncSandbox
sandbox = await AsyncSandbox.create({"allow_write": ["/tmp"]})
text = await sandbox.sh("echo hello").text()
data = await sandbox.sh("printf '{\"ok\": true}'").json()
result = await sandbox.exec("python3", ["-c", "print('hi')"]).output()
Асинхронные команды принимают ту же опцию timeout:
import subprocess
try:
await sandbox.sh("sleep 60").text(timeout=1.0)
except subprocess.TimeoutExpired:
print("cancelled")
Ненулевой код выхода вызывает SandboxCommandError:
from zerobox import Sandbox, SandboxCommandError
sandbox = Sandbox.create()
try:
sandbox.sh("exit 1").text()
except SandboxCommandError as e:
print(e.code, e.stderr)
Передавайте API-ключи, которые процесс в песочнице никогда не видит. Прокси подставляет реальное значение только для одобренных хостов.
import os
from zerobox import Sandbox
sandbox = Sandbox.create({
"secrets": {
"OPENAI_API_KEY": {
"value": os.environ["OPENAI_API_KEY"],
"hosts": ["api.openai.com"],
},
"GITHUB_TOKEN": {
"value": os.environ["GITHUB_TOKEN"],
"hosts": ["api.github.com"],
},
},
})
sandbox.sh('curl -H "Authorization: Bearer $OPENAI_API_KEY" https://api.openai.com/v1/models').text()
Информацию о том, как работает подстановка заполнителей, см. в основном README.
Записывайте изменения файловой системы и автоматически откатывайте их:
sandbox = Sandbox.create({
"allow_write": ["."],
"restore": True,
})
sandbox.sh("npm install").text()
Запись без отката:
sandbox = Sandbox.create({
"allow_write": ["."],
"snapshot": True,
"snapshot_exclude": ["node_modules"],
})
sandbox.sh("npm install").text()
Передайте timeout (в секундах) любому терминатору:
import subprocess
try:
sandbox.sh("sleep 60").text(timeout=1.0)
except subprocess.TimeoutExpired:
print("cancelled")
sandbox = Sandbox.create({
"env": {"NODE_ENV": "production"},
"allow_env": ["PATH", "HOME"],
"deny_env": ["AWS_SECRET_ACCESS_KEY"],
})
См. основной README, чтобы узнать, что наследуется по умолчанию, и эквиваленты в CLI.
Sandbox.create(options) принимает dataclass SandboxOptions или обычный dict. Все поля необязательны.
| Поле | Тип | Описание |
|---|---|---|
profile | str | list[str] | Именованный профиль(и). Список объединяется слева направо. По умолчанию "workspace". |
allow_read / deny_read | list[str] | Доступные для чтения / заблокированные пути. |
allow_write / deny_write | list[str] | Доступные для записи / заблокированные пути. |
allow_net | bool | list[str] | True разрешает всё. Список ограничивает доступ указанными доменами. |
deny_net | list[str] | Заблокированные домены. |
allow_all | bool | Полный доступ к файловой системе и сети. |
no_sandbox | bool | Полностью отключить песочницу. |
strict_sandbox | bool | Завершиться с ошибкой вместо перехода к более слабой изоляции. |
cwd | str | Рабочий каталог. |
env | dict[str, str] | Явные переменные окружения. |
allow_env | bool | list[str] | Наследовать переменные окружения родительского процесса. |
deny_env | list[str] | Заблокированные переменные окружения. |
snapshot | bool | Записывать изменения файловой системы. |
restore | bool | Записывать и откатывать изменения после выхода. Подразумевает snapshot. |
snapshot_paths / snapshot_exclude | list[str] | Отслеживаемые пути / исключаемые шаблоны. |
secrets | dict[str, SecretConfig] | Секреты с областями действия для каждого хоста. |
debug | bool | Выводить конфигурацию песочницы в stderr. |
Неизвестные ключи dict (например, случайный allowWrite вместо allow_write) вызывают TypeError во время создания.
Sandbox.py(code) запускает тот python3, который находится в PATH внутри песочницы. Если ваш активный интерпретатор находится вне доступных для чтения корней песочницы (например, управляемые через uv Python в ~/.local/share/uv/), используйте вместо этого:
import sys
sandbox = Sandbox.create({"allow_read": [sys.prefix]})
sandbox.exec(sys.executable, ["-c", "print('hi')"]).text()
zerobox)zerobox)Apache-2.0