English | 简体中文
eci-as-sandbox
ECI-backed sandbox manager built on alibabacloud-eci20180808 with a lightweight API for managing container-group sandboxes.
Install
pdm add eci-as-sandbox
Environment
The client auto-loads a .env file (searching upward from the working directory). You can also pass env_file=... or explicit credentials.
Required Alibaba Cloud credentials:
set ALIBABA_CLOUD_ACCESS_KEY_ID=...
set ALIBABA_CLOUD_ACCESS_KEY_SECRET=...
set ALIBABA_CLOUD_REGION_ID=cn-shanghai
Optional overrides:
set ECI_SANDBOX_ACCESS_KEY_ID=...
set ECI_SANDBOX_ACCESS_KEY_SECRET=...
set ECI_SANDBOX_REGION_ID=cn-shanghai
set ECI_SANDBOX_ENDPOINT=eci.cn-shanghai.aliyuncs.com
set ECI_SANDBOX_TIMEOUT_MS=60000
If you use a private image, configure registry credentials in ECI.
Quick start (sync)
from eci_as_sandbox import EciSandbox
client = EciSandbox()
result = client.create(
image="registry.cn-hangzhou.aliyuncs.com/eci_open/nginx:latest",
name="sandbox-demo",
cpu=1.0,
memory=2.0,
v_switch_id="vsw-xxx",
security_group_id="sg-xxx",
ports=[{"port": 8080, "protocol": "TCP"}],
)
if result.success and result.sandbox:
sandbox = result.sandbox
info = sandbox.info()
print(info.data.status)
sandbox.delete()
Async quick start
import asyncio
from eci_as_sandbox import AsyncEciSandbox
async def main() -> None:
client = AsyncEciSandbox()
result = await client.create(
image="registry.cn-hangzhou.aliyuncs.com/eci_open/nginx:latest",
name="sandbox-demo",
cpu=1.0,
memory=2.0,
v_switch_id="vsw-xxx",
security_group_id="sg-xxx",
)
if result.success and result.sandbox:
info = await result.sandbox.info()
print(info.data.status)
asyncio.run(main())
Command helpers
exec_command runs a list-form command. With sync=True (default) it uses the ECI WebSocket stream to collect output. timeout is in seconds and caps the stream duration (default 600 seconds, max 600). Use sync=False if you want the WebSocket/HTTP URLs without waiting.
result = sandbox.exec_command(
["/bin/sh", "-c", "for i in 1 2 3; do echo tick-$i; sleep 2; done"],
timeout=3,
)
print(result.output)
bash runs a shell command via bash -lc and supports exec_dir.
result = sandbox.bash(
command="pwd; ls -la",
exec_dir="/tmp",
timeout=5,
)
print(result.output)
Listing
result = client.list(limit=10, status="Running")
print(result.sandbox_ids)
Long command execution (WebSocket)
ECI's API has a 2048-byte command limit. For longer commands, use bash_ws which sends commands through WebSocket stdin (no length limit).
# Execute a very long command (e.g., inline Python script)
long_script = """python3 << 'EOF'
import json
# ... hundreds of lines of code ...
print(json.dumps({"status": "done"}))
EOF
"""
result = client.bash_ws(
sandbox_id=sandbox_id,
command=long_script,
exec_dir="/workspace",
timeout=60,
)
print(result.output)
write_file_ws writes large content to a file via WebSocket:
result = client.write_file_ws(
sandbox_id=sandbox_id,
file_path="/tmp/large_script.py",
content="# Very long file content...\n" * 1000,
timeout=30,
)
Tmux session management
For non-blocking command execution with output capture, use tmux methods. Long commands are automatically handled via WebSocket file transfer.
# Start a command in tmux (non-blocking)
start_result = client.tmux_start(
sandbox_id=sandbox_id,
command="python train.py --epochs 100",
exec_dir="/workspace",
)
print(f"Session: {start_result.session_id}")
# Poll for status and partial output
poll_result = client.tmux_poll(
sandbox_id=sandbox_id,
session_id=start_result.session_id,
)
print(f"Status: {poll_result.status}") # RUNNING, COMPLETED, NOT_FOUND
print(f"Output: {poll_result.output}")
# Wait for completion with exponential backoff
wait_result = client.tmux_wait(
sandbox_id=sandbox_id,
session_id=start_result.session_id,
timeout=300, # max wait time
)
print(f"Exit code: {wait_result.exit_code}")
print(f"Output: {wait_result.output}")
# Kill a session manually
client.tmux_kill(sandbox_id=sandbox_id, session_id=start_result.session_id)
# List all tmux sessions
list_result = client.tmux_list(sandbox_id=sandbox_id)
print(list_result.data) # [{"session_id": "...", "created": "...", "attached": False}]
API Reference
Client Methods
| Method | Description |
|---|---|
create(image, name, cpu, memory, ...) |
Create a new sandbox container |
get(sandbox_id) |
Get sandbox instance by ID |
get_sandbox(sandbox_id) |
Get sandbox info |
list(limit, status, tags, ...) |
List sandboxes |
delete(sandbox_id, force) |
Delete a sandbox |
restart(sandbox_id) |
Restart a sandbox |
exec_command(sandbox_id, command, ...) |
Execute command (list form) |
bash(sandbox_id, command, exec_dir, ...) |
Execute bash command |
bash_ws(sandbox_id, command, exec_dir, ...) |
Execute bash via WebSocket (unlimited length) |
write_file_ws(sandbox_id, file_path, content, ...) |
Write file via WebSocket (unlimited length) |
tmux_start(sandbox_id, command, ...) |
Start command in tmux session |
tmux_poll(sandbox_id, session_id, ...) |
Poll tmux session status |
tmux_wait(sandbox_id, session_id, timeout, ...) |
Wait for tmux session completion |
tmux_kill(sandbox_id, session_id) |
Kill tmux session |
tmux_list(sandbox_id) |
List all tmux sessions |
Metadata
Release files for eci-as-sandbox 0.2.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| eci_as_sandbox-0.2.5.tar.gz | 32.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| eci_as_sandbox-0.2.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 65.1 kB
Release files / eci_as_sandbox-0.2.5.tar.gz
| Download URL | eci_as_sandbox-0.2.5.tar.gz |
|---|---|
| Size | 32.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fc7e70454389893627ae80d37071cbfcc0d5c1fff3c303ef084930bd28d38a27
|
|
BLAKE2b-256 checksum How to use checksums |
0a067064d6595ffef6d2673c4fbf1861248bc685a4fdfae05a6ffb6480621322
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 22, 2026.
Transparency logRelease files / eci_as_sandbox-0.2.5-py3-none-any.whl
| Download URL | eci_as_sandbox-0.2.5-py3-none-any.whl |
|---|---|
| Size | 32.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ec9569a61d9d43bc14bff4e4986cd0f3e7e84f839d0d41e2303f246c320a49b0
|
|
BLAKE2b-256 checksum How to use checksums |
1ee367a6d60e4dc7257231b9c8439cc712b261636386b14099908f0cd12c9174
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 22, 2026.
Transparency log