Skip to main content

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+
  • httpx for HTTP requests
  • websockets for 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)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pipeops_rexec-1.1.0-py3-none-any.whl (3.9 kB view details)

Uploaded Python 3

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

Hashes for pipeops_rexec-1.1.0.tar.gz
Algorithm Hash digest
SHA256 5c420006759a8707a8f5236840c26a4a27ddf8cf9eb91e89134c4a6bf92f3e4c
MD5 58ace07c57783ee9620abe9889644411
BLAKE2b-256 ace89b41439bb1da06f2787d710bf6a7592dc0edbd095cce5a8123723b364c11

See more details on using hashes here.

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

Hashes for pipeops_rexec-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9ac0951092cc343c5ab15a76e60cfcd2fb3beba7a974bc713a48e12231b43a28
MD5 a94b27a0bc34464e037161f66e7c8969
BLAKE2b-256 a70181e882748c1d4aa381d96718d53b71c2fe4e3352ce9969b63cb84415869f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page