Rexec Python SDK
Official Python SDK for Rexec - Terminal as a Service.
Installation
pip install pipeops-rexec
Quick Start
import asyncio
from rexec import RexecClient
async def main():
async with RexecClient("https://your-instance.com", "your-token") as client:
# Create a container
container = await client.containers.create(
image="ubuntu",
name="my-sandbox"
)
print(f"Created container: {container.id}")
# Connect to terminal
async with client.terminal.connect(container.id) as term:
await term.write(b"echo 'Hello from Rexec!'\n")
# Read output
data = await term.read()
print(data.decode())
# Clean up
await client.containers.delete(container.id)
asyncio.run(main())
API Reference
RexecClient
from rexec import RexecClient
# Create client (use as context manager for automatic cleanup)
async with RexecClient(
base_url="https://your-instance.com",
token="your-api-token",
timeout=30.0, # optional
) as client:
...
# Or manage manually
client = RexecClient("https://your-instance.com", "your-token")
try:
...
finally:
await client.close()
Containers
# List all containers
containers = await client.containers.list()
for c in containers:
print(f"{c.name}: {c.status}")
# Get a specific container
container = await client.containers.get(container_id)
# Create a container
container = await client.containers.create(
image="ubuntu",
name="my-container",
environment={"MY_VAR": "value"},
labels={"project": "demo"}
)
# Start a container
await client.containers.start(container_id)
# Stop a container
await client.containers.stop(container_id)
# Delete a container
await client.containers.delete(container_id)
Files
# List files in a directory
files = await client.files.list(container_id, "/home")
for f in files:
prefix = "📁" if f.is_dir else "📄"
print(f"{prefix} {f.name}")
# Download a file
content = await client.files.download(container_id, "/etc/passwd")
print(content.decode())
# Upload a file
await client.files.upload(
container_id,
"/home/script.py",
b"print('hello world')"
)
# Create a directory
await client.files.mkdir(container_id, "/home/mydir")
# Delete a file
await client.files.delete(container_id, "/home/script.py")
Terminal
# Connect to terminal (recommended: use as context manager)
async with client.terminal.connect(
container_id,
cols=120,
rows=40,
timeout=30.0
) as term:
# Send commands
await term.write(b"ls -la\n")
# Read output
data = await term.read()
print(data.decode())
# Resize terminal
await term.resize(150, 50)
# Or iterate over output
async with client.terminal.connect(container_id) as term:
await term.write(b"echo hello && sleep 1 && echo world\n")
async for data in term:
print(data.decode(), end="")
Examples
Run a Script and Capture Output
async def run_script(client: RexecClient, container_id: str, script: str) -> str:
output = []
async with client.terminal.connect(container_id) as term:
await term.write(f"{script}\nexit\n".encode())
async for data in term:
output.append(data.decode())
return "".join(output)
# Usage
result = await run_script(client, container.id, "apt update && apt install -y curl")
print(result)
Batch Container Operations
async def create_batch(client: RexecClient, count: int) -> list[Container]:
import asyncio
tasks = [
client.containers.create(
image="ubuntu",
name=f"worker-{i}"
)
for i in range(count)
]
return await asyncio.gather(*tasks)
# Create 5 containers in parallel
containers = await create_batch(client, 5)
File Sync
import os
from pathlib import Path
async def sync_directory(
client: RexecClient,
container_id: str,
local_path: Path,
remote_path: str
):
"""Sync a local directory to a container."""
await client.files.mkdir(container_id, remote_path)
for item in local_path.iterdir():
remote_item = f"{remote_path}/{item.name}"
if item.is_file():
content = item.read_bytes()
await client.files.upload(container_id, remote_item, content)
print(f"Uploaded: {remote_item}")
elif item.is_dir():
await sync_directory(client, container_id, item, remote_item)
Error Handling
from rexec import RexecClient, RexecAPIError, RexecConnectionError
try:
container = await client.containers.get("invalid-id")
except RexecAPIError as e:
print(f"API Error {e.status_code}: {e.message}")
except RexecConnectionError as e:
print(f"Connection Error: {e}")
Type Hints
The SDK is fully typed for excellent IDE support:
from rexec import (
RexecClient,
Container,
CreateContainerRequest,
FileInfo,
Terminal,
)
container: Container = await client.containers.create(image="ubuntu")
files: list[FileInfo] = await client.files.list(container.id, "/")
Requirements
- Python 3.9+
httpxfor HTTP requestswebsocketsfor terminal connections
License
MIT License - see LICENSE for details.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
pipeops_rexec-1.1.0.tar.gz
(4.3 kB
view details)
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pipeops_rexec-1.1.0.tar.gz.
File metadata
- Download URL: pipeops_rexec-1.1.0.tar.gz
- Upload date:
- Size: 4.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5c420006759a8707a8f5236840c26a4a27ddf8cf9eb91e89134c4a6bf92f3e4c
|
|
| MD5 |
58ace07c57783ee9620abe9889644411
|
|
| BLAKE2b-256 |
ace89b41439bb1da06f2787d710bf6a7592dc0edbd095cce5a8123723b364c11
|
File details
Details for the file pipeops_rexec-1.1.0-py3-none-any.whl.
File metadata
- Download URL: pipeops_rexec-1.1.0-py3-none-any.whl
- Upload date:
- Size: 3.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9ac0951092cc343c5ab15a76e60cfcd2fb3beba7a974bc713a48e12231b43a28
|
|
| MD5 |
a94b27a0bc34464e037161f66e7c8969
|
|
| BLAKE2b-256 |
a70181e882748c1d4aa381d96718d53b71c2fe4e3352ce9969b63cb84415869f
|