Skip to main content

Official Python client for Runbox - secure code execution API

Project description

Runbox Python Client

Official Python client for Runbox - a fast, secure API for running code in isolated containers.

PyPI version CI License: MIT

Installation

pip install runbox-py

Quick Start

from runbox_client import Client

# Create a client
client = Client(
    url="http://localhost:8080",
    api_key="your-api-key"
)

# Step 1: Set up a container and get environment info
setup = client.setup(
    identifier="my-session",
    language="python"
)

print(setup.container_id)  # => "runbox-my-session-python"
print(setup.environment_snapshot.runtime_version)  # => "3.11.6"
print(setup.environment_snapshot.packages["requests"])  # => "2.31.0"

# Step 2: Run code in the container
result = client.run(
    container_id=setup.container_id,
    files=[{"path": "main.py", "content": "print('Hello!')"}],
    run_command="python main.py"
)

print(result.stdout)  # => "Hello!\n"
print(result.success)  # => True

Configuration

Using Environment Variables

export RUNBOX_URL=http://localhost:8080
export RUNBOX_API_KEY=your-api-key
from runbox_client import Client

# Will use environment variables
client = Client()

Explicit Configuration

client = Client(
    url="http://localhost:8080",
    api_key="your-api-key",
    timeout=120  # HTTP timeout in seconds
)

Usage

Setting Up a Container

setup = client.setup(
    identifier="session-123",
    language="python",
    env={"API_KEY": "secret"},      # Optional: environment variables
    memory="512m",                   # Optional: memory limit
    network_allow=["api.stripe.com"] # Optional: allowed network destinations
)

# Access environment information
print(setup.container_id)  # => "runbox-session-123-python"
print(setup.cached)        # => False (True if container was reused)

env = setup.environment_snapshot
print(env.os_name)          # => "debian"
print(env.os_version)       # => "12"
print(env.runtime_name)     # => "python"
print(env.runtime_version)  # => "3.11.6"
print(env.packages)         # => {"pip": "23.0.1", "requests": "2.31.0", ...}

Running Code

result = client.run(
    container_id="runbox-session-123-python",
    files=[{"path": "main.py", "content": "print('Hello!')"}],
    run_command="python main.py",
    env={"DEBUG": "true"},  # Optional: runtime environment variables
    timeout=30              # Optional: execution timeout in seconds
)

print(result.success)          # => True
print(result.exit_code)        # => 0
print(result.stdout)           # => "Hello!\n"
print(result.stderr)           # => ""
print(result.execution_time_ms) # => 42
print(result.timed_out)        # => False

Installing Dependencies On-The-Fly

Install new dependencies before running code:

# Python example
result = client.run(
    container_id=container_id,
    files=[{"path": "main.py", "content": "import requests; print(requests.__version__)"}],
    run_command="python main.py",
    new_dependencies=["requests==2.31.0", "pytest"]
)

print(result.packages)  # => {"pip": "23.0.1", "requests": "2.31.0", "pytest": "7.4.0", ...}

# Ruby example
result = client.run(
    container_id=container_id,
    files=[{"path": "main.rb", "content": "require 'rake'; puts Rake::VERSION"}],
    run_command="ruby main.rb",
    new_dependencies=["rake", "rspec"]
)

# Shell example (uses apk)
result = client.run(
    container_id=container_id,
    files=[{"path": "script.sh", "content": "#!/bin/sh\ncurl --version"}],
    run_command="sh script.sh",
    new_dependencies=["curl", "jq", "git"]
)

Note: The packages field is only included in the result when new_dependencies are provided.

Async Support

import asyncio
from runbox_client import AsyncClient

async def main():
    async with AsyncClient(url="http://localhost:8080", api_key="your-api-key") as client:
        # Setup container
        setup = await client.setup(
            identifier="session-123",
            language="python"
        )
        
        # Run code
        result = await client.run(
            container_id=setup.container_id,
            files=[{"path": "main.py", "content": "print('Hello!')"}],
            run_command="python main.py"
        )
        
        print(result.stdout)

asyncio.run(main())

Cleanup Containers

deleted = client.delete_containers("session-123")
print(deleted)  # => ["runbox-session-123-python"]

Check Health

health = client.health()
print(health.status)  # => "healthy"
print(health.version) # => "1.0.0"

API Reference

client.setup(identifier, language, **options)

Set up a container and get environment information.

Parameters:

  • identifier (str, required): Unique identifier for container reuse
  • language (str, required): Programming language ("python", "ruby", "shell")
  • env (dict, optional): Environment variables to set
  • timeout (int, optional): Default timeout in seconds
  • memory (str, optional): Memory limit (e.g., "256m", "1g")
  • network_allow (list[str], optional): Allowed network destinations

Returns: SetupResult with:

  • container_id: Container ID to use in run() calls
  • cached: Whether container was reused
  • environment_snapshot: Environment information (OS, runtime, packages)

client.run(container_id, files, run_command, **options)

Run code in a container that was set up via setup().

Parameters:

  • container_id (str, required): Container ID from setup() response
  • files (list[dict], required): Files to write before running
  • run_command (str, required): Command to run
  • env (dict, optional): Runtime environment variables
  • timeout (int, optional): Execution timeout in seconds

Returns: RunResult with:

  • success: Whether run succeeded (exit code 0)
  • exit_code: Process exit code
  • stdout: Standard output
  • stderr: Standard error
  • execution_time_ms: Execution time in milliseconds
  • timed_out: Whether run timed out

Error Handling

from runbox_client import (
    Client,
    AuthenticationError,
    NotFoundError,
    ValidationError,
    RunError,
    ConnectionError,
)

try:
    setup = client.setup(identifier="test", language="python")
    result = client.run(
        container_id=setup.container_id,
        files=[{"path": "main.py", "content": "print('hi')"}],
        run_command="python main.py"
    )
except AuthenticationError:
    print("Invalid API key")
except NotFoundError:
    print("Container not found (did you call setup first?)")
except ValidationError as e:
    print(f"Invalid request: {e}")
except RunError as e:
    print(f"Run failed: {e}")
except ConnectionError as e:
    print(f"Could not connect: {e}")

Development

Setup

python3 -m venv venv
source venv/bin/activate
pip install -e ".[dev]"

Running Tests

pytest

Running Integration Tests

Integration tests require a running Runbox server:

# Start Runbox server (in another terminal)
cd ../runbox
docker-compose up

# Run integration tests
export RUNBOX_URL=http://localhost:8080
export RUNBOX_API_KEY=your-api-key
python examples/integration_test.py

Linting & Typing

ruff check .
mypy src

CI/CD

  • CI: Runs on every push and PR

    • Tests on Python 3.9, 3.10, 3.11, 3.12
    • Linting with Ruff
    • Type checking with MyPy
    • Integration tests against live Runbox server
  • CD: Publishes to PyPI on version tags

License

MIT License - see LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

runbox_py-1.1.1.tar.gz (11.5 kB view details)

Uploaded Source

Built Distribution

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

runbox_py-1.1.1-py3-none-any.whl (7.6 kB view details)

Uploaded Python 3

File details

Details for the file runbox_py-1.1.1.tar.gz.

File metadata

  • Download URL: runbox_py-1.1.1.tar.gz
  • Upload date:
  • Size: 11.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for runbox_py-1.1.1.tar.gz
Algorithm Hash digest
SHA256 50793a9ec82ce550941b313dffd590e072492a8be0e0b30518616fd0107d40f9
MD5 0a78d6530f5bdf9ea7d8cc63fc7bf1a3
BLAKE2b-256 b0ccaa239a4a70878341201f131a28494828a5e1a86c92f64d92d406a324db89

See more details on using hashes here.

Provenance

The following attestation bundles were made for runbox_py-1.1.1.tar.gz:

Publisher: cd.yml on kaka-ruto/runbox-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file runbox_py-1.1.1-py3-none-any.whl.

File metadata

  • Download URL: runbox_py-1.1.1-py3-none-any.whl
  • Upload date:
  • Size: 7.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for runbox_py-1.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 1e0fb4724c5f901a58907d3918f9775947f070ae4e8e90a6a2aeeb9715a378aa
MD5 6c2e9bad6b8943951ef979f40d52b470
BLAKE2b-256 dc1cc0a38a28c1ac1b6b0c513fb171c7fb2372eda165d150d28be7af65331cb2

See more details on using hashes here.

Provenance

The following attestation bundles were made for runbox_py-1.1.1-py3-none-any.whl:

Publisher: cd.yml on kaka-ruto/runbox-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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