Skip to main content

Official Python SDK for Bunnyshell Sandboxes

Project description

Bunnyshell Python SDK

PyPI version Python 3.8+ License: MIT

Official Python SDK for Bunnyshell Sandboxes - Execute code safely in isolated microVM environments.

Features

  • 🚀 47/47 Features - 100% API coverage
  • 🔒 Type Safe - Full Pydantic models with auto-complete
  • Async Support - Native async/await for all operations
  • 🌊 WebSocket Streaming - Real-time code execution, terminal, file watching
  • 🎨 Rich Outputs - Automatic capture of plots, images, DataFrames
  • 🔐 Security First - Environment variables for secrets, execution timeouts
  • 📦 Context Managers - Automatic cleanup with with statement
  • 🐍 Pythonic API - Follows Python best practices

Installation

pip install bunnyshell

For WebSocket features (optional):

pip install bunnyshell[websockets]

Quick Start

from bunnyshell import Sandbox

# Create sandbox
with Sandbox.create(template="code-interpreter", api_key="your-api-key") as sandbox:
    # Execute Python code
    result = sandbox.run_code("""
import pandas as pd
df = pd.DataFrame({'a': [1, 2, 3], 'b': [4, 5, 6]})
print(df.sum())
    """)
    
    print(result.stdout)
    # Output: a    6
    #         b   15

Environment Variables (IMPORTANT!)

✅ ALWAYS pass secrets via environment variables:

# ✅ GOOD: Secrets via environment variables
result = sandbox.run_code(
    """
import os
api_key = os.getenv('OPENAI_API_KEY')
# Use api_key safely...
    """,
    env={"OPENAI_API_KEY": "sk-..."}
)

# ❌ BAD: Never hardcode secrets
# result = sandbox.run_code('api_key = "sk-..."')  # DON'T DO THIS!

Core Features

Code Execution

# Synchronous execution
result = sandbox.run_code("print('Hello')")

# With environment variables
result = sandbox.run_code(
    "import os; print(os.getenv('MY_VAR'))",
    env={"MY_VAR": "value"}
)

# Async execution (non-blocking)
execution_id = sandbox.run_code_async("import time; time.sleep(10)")

# Background execution (fire-and-forget)
execution_id = sandbox.run_code_background("# long task...")

# IPython/Jupyter-style
result = sandbox.run_ipython("df.describe()")

Real-time Streaming (WebSocket)

import asyncio

async def stream():
    async for message in sandbox.run_code_stream("""
import time
for i in range(5):
    print(f"Step {i+1}")
    time.sleep(1)
    """):
        if message['type'] == 'stdout':
            print(message['data'], end='')

asyncio.run(stream())

File Operations

# Write file
sandbox.files.write('/workspace/data.txt', 'Hello, World!')

# Read file
content = sandbox.files.read('/workspace/data.txt')

# List directory
files = sandbox.files.list('/workspace')
for file in files:
    print(f"{file.name} ({file.size_kb:.2f}KB)")

# Upload local file
sandbox.files.upload('./local.txt', '/workspace/remote.txt')

# Download remote file
sandbox.files.download('/workspace/remote.txt', './local.txt')

# Check existence
if sandbox.files.exists('/workspace/data.txt'):
    print("File exists!")

# Remove file/directory
sandbox.files.remove('/workspace/data.txt')

# Create directory
sandbox.files.mkdir('/workspace/mydir')

# Watch filesystem (WebSocket)
async for event in sandbox.files.watch('/workspace'):
    print(f"{event['event']}: {event['path']}")

Commands

# Run shell command
result = sandbox.commands.run('ls -la /workspace')
print(result.stdout)

# With environment variables
result = sandbox.commands.run(
    'echo "Key: $API_KEY"',
    env={'API_KEY': 'secret'}
)

# Custom working directory
result = sandbox.commands.run(
    'pwd',
    working_dir='/workspace/myproject'
)

Environment Variables

# Get all
env_vars = sandbox.env.get_all()

# Set all (replace)
sandbox.env.set_all({'API_KEY': 'sk-...', 'DEBUG': 'true'})

# Update (merge)
sandbox.env.update({'NEW_VAR': 'value'})

# Delete
sandbox.env.delete(['VAR_TO_DELETE'])

# Get single
value = sandbox.env.get('API_KEY')

# Set single
sandbox.env.set('API_KEY', 'sk-...')

Process Management

# List processes
processes = sandbox.list_processes()
for proc in processes:
    print(f"{proc.pid}: {proc.name} (CPU: {proc.cpu_percent}%)")

# Kill process
sandbox.kill_process(1234)

Metrics & Health

# Get metrics
metrics = sandbox.get_metrics_snapshot()
print(f"Total executions: {metrics.total_executions}")
print(f"Uptime: {metrics.uptime_seconds}s")

# Health check
health = sandbox.get_health()
print(f"Status: {health.status}")

# Cache management
cache_stats = sandbox.cache.stats()
print(f"Cache size: {cache_stats.cache.size}")

sandbox.cache.clear()

Desktop Automation

# Note: Requires 'desktop' template
sandbox = Sandbox.create(template='desktop', api_key='...')

# Mouse operations
sandbox.desktop.mouse_click(x=500, y=300, button='left')
sandbox.desktop.mouse_move(x=600, y=400)
sandbox.desktop.drag_drop(from_x=100, from_y=100, to_x=300, to_y=300)

# Keyboard
sandbox.desktop.keyboard_type('Hello, World!')
sandbox.desktop.keyboard_press('Return')
sandbox.desktop.keyboard_press('Control_L+c')  # Ctrl+C

# Clipboard
sandbox.desktop.clipboard_set('text to copy')
content = sandbox.desktop.clipboard_get()

# Screenshots
screenshot = sandbox.desktop.screenshot()
with open('screenshot.png', 'wb') as f:
    f.write(screenshot)

# OCR (text recognition)
text = sandbox.desktop.ocr()
print(f"Found text: {text}")

# Find elements
element = sandbox.desktop.find_element(text='Button')
if element:
    sandbox.desktop.mouse_click(x=element['x'], y=element['y'])

# VNC connection
vnc_info = sandbox.desktop.get_vnc_url()
print(f"VNC URL: {vnc_info['url']}")

Interactive Terminal (WebSocket)

import asyncio

async def terminal_session():
    async with sandbox.terminal.connect() as term:
        # Send commands
        await sandbox.terminal.send_input(term, 'ls -la\n')
        
        # Receive output
        async for message in sandbox.terminal.iter_output(term):
            if message['type'] == 'output':
                print(message['data'], end='')

asyncio.run(terminal_session())

Advanced Configuration

sandbox = Sandbox.create(
    template='code-interpreter',
    api_key='your-api-key',
    vcpu=4,              # 4 vCPUs
    memory_mb=4096,      # 4GB RAM
    disk_gb=20,          # 20GB disk
    region='us-west-2',  # Specific region
    timeout=600,         # 10 minute timeout
    env_vars={           # Pre-set environment variables
        'DATABASE_URL': 'postgres://...',
        'API_KEY': 'sk-...'
    }
)

Error Handling

from bunnyshell.errors import (
    BunnyshellError,
    AuthenticationError,
    NotFoundError,
    FileNotFoundError,
    CodeExecutionError,
    RateLimitError,
    ServerError
)

try:
    with Sandbox.create(template='code-interpreter', api_key='...') as sandbox:
        result = sandbox.run_code("print('Hello')")
        
except AuthenticationError as e:
    print(f"Auth failed: {e.message}")
    print(f"Request ID: {e.request_id}")
    
except FileNotFoundError as e:
    print(f"File not found: {e.path}")
    
except CodeExecutionError as e:
    print(f"Code execution failed: {e.message}")
    print(f"Exit code: {e.exit_code}")
    
except RateLimitError as e:
    print(f"Rate limited: {e.message}")
    
except BunnyshellError as e:
    print(f"API error: {e.message}")
    print(f"Status code: {e.status_code}")

Best Practices

1. Always Use Context Managers

# ✅ GOOD: Automatic cleanup
with Sandbox.create(...) as sandbox:
    # Work here
    pass
# Sandbox automatically deleted

# ❌ BAD: Manual cleanup (easy to forget)
sandbox = Sandbox.create(...)
# ... work ...
sandbox.kill()  # Easy to forget if error occurs!

2. Set Timeouts

# Prevent infinite execution
result = sandbox.run_code(code, timeout=30)

3. Optimize Performance

# Set environment variables once
sandbox.env.set_all({'API_KEY': 'sk-...', 'DB_URL': '...'})

# Now available in all executions
for i in range(100):
    sandbox.run_code('...')  # Env vars already set

Use Cases

OpenAI: ChatGPT Code Interpreter

def execute_user_code(user_code: str):
    with Sandbox.create(template="code-interpreter") as sandbox:
        result = sandbox.run_code(user_code, timeout=30)
        return {
            "output": result.stdout,
            "error": result.stderr,
            "rich_outputs": result.rich_outputs  # Images, plots
        }

Stripe: Payment Reports

with Sandbox.create(template="code-interpreter") as sandbox:
    sandbox.env.set('STRIPE_SECRET_KEY', os.getenv('STRIPE_SECRET_KEY'))
    
    result = sandbox.run_code("""
import stripe
stripe.api_key = os.environ['STRIPE_SECRET_KEY']
charges = stripe.Charge.list(limit=100)
# Generate report...
    """)

Documentation

License

MIT License - See LICENSE file for details.

Support

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

bunnyshell-0.1.10.tar.gz (124.9 kB view details)

Uploaded Source

Built Distribution

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

bunnyshell-0.1.10-py3-none-any.whl (67.6 kB view details)

Uploaded Python 3

File details

Details for the file bunnyshell-0.1.10.tar.gz.

File metadata

  • Download URL: bunnyshell-0.1.10.tar.gz
  • Upload date:
  • Size: 124.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for bunnyshell-0.1.10.tar.gz
Algorithm Hash digest
SHA256 1e1c9b72f7382d0feb691e3cd77ce3a8b8d9cd00d804f33ea6fa14a63acdb179
MD5 d8af6d8573fc25a83f2afad58e6a3f91
BLAKE2b-256 2ba247fd2b83e716b6de3ad97c79346d0ca23e72bca409ed37f94c841eabc7fc

See more details on using hashes here.

File details

Details for the file bunnyshell-0.1.10-py3-none-any.whl.

File metadata

  • Download URL: bunnyshell-0.1.10-py3-none-any.whl
  • Upload date:
  • Size: 67.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for bunnyshell-0.1.10-py3-none-any.whl
Algorithm Hash digest
SHA256 d83e8f397b965f984030bc72db8f0d46a98af67f9c624fa03b9fa6edb173ab99
MD5 2466773a77a9e6ca24e2c4c1326df60a
BLAKE2b-256 c3d7fb482e06ed814719a2b3fb56ec3801e272988ad244eb93b24280b6734652

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