DOCS

Python SDK

The official Python SDK — spawn sandboxes, run code and commands, and move files. Mirrors the e2b Sandbox shape.

pip install qbox-sh

The SDK mirrors the e2b Sandbox shape, so migrating is mostly a one-line import change.

A TypeScript SDK is coming soon. Until then, drive qbox from TypeScript via the REST API.

Authentication

The SDK reads QBOX_API_KEY and QBOX_BASE_URL from the environment, or you pass them explicitly via qbox.configure(...):

export QBOX_API_KEY=qbox_...
export QBOX_BASE_URL=https://qbox.your-company.internal
import qbox

qbox.configure(api_key="qbox_...", base_url="https://qbox.acme.internal")

Create an API key in the dashboard under API Keys.

Quickstart

import qbox

with qbox.Sandbox.create(template="python-3.12") as sandbox:
    # Run code in a stateful interpreter and read rich output.
    result = sandbox.run_code("import pandas as pd; pd.DataFrame({'a':[1,2,3]}).describe()")
    print(result.text)

    # Run a shell command.
    proc = sandbox.commands.run("python --version")
    print(proc.stdout)

The with block kills the sandbox on exit. To keep it running, call qbox.Sandbox.create(...) without the context manager and kill() when done.

Sandboxes

sandbox = qbox.Sandbox.create(template="python-3.12")   # spawn from a template
sandbox = qbox.Sandbox.connect("sb_018f…")               # reconnect by id
info = sandbox.get_info()                                 # status, template, host
sandbox.set_timeout(600)                                  # extend auto-kill window (default 5 min)
for s in qbox.Sandbox.list():                             # active sandboxes
    print(s.id, s.status)
sandbox.kill()

Run code

run_code executes in a stateful kernel (variables persist across calls within a context). Outputs can be text, HTML, PNG, or JSON.

out = sandbox.run_code("x = 40")
out = sandbox.run_code("print(x + 2)")   # → 42; state carried over
print(out.text)

# Stream output as it's produced:
for event in sandbox.run_code_stream("for i in range(3): print(i)"):
    print(event)

Commands

# Foreground — blocks, returns stdout/stderr/exit code.
proc = sandbox.commands.run("pytest -q")
print(proc.stdout, proc.exit_code)

# Background — returns a handle you can stream and kill.
handle = sandbox.commands.run("python server.py", background=True)
for line in handle:          # stream combined output
    print(line)
handle.kill()

sandbox.commands.list()      # running processes

Files

sandbox.files.write("/tmp/data.csv", "a,b\n1,2\n")
sandbox.files.append("/tmp/data.csv", "3,4\n")
text = sandbox.files.read("/tmp/data.csv")
entries = sandbox.files.list("/tmp")
sandbox.files.mkdir("/tmp/out")
sandbox.files.upload("./local.bin", "/tmp/local.bin")
sandbox.files.download("/tmp/result.json", "./result.json")
sandbox.files.rename("/tmp/a", "/tmp/b")
sandbox.files.remove("/tmp/b")
print(sandbox.files.exists("/tmp/data.csv"))

Interactive shell

Install the extra and open a PTY straight into the VM (the template must have SSH enabled):

pip install "qbox[shell]"
sandbox.shell()   # interactive PTY

Templates

for t in qbox.Templates.list():
    print(t.id, t.name, t.status)
t = qbox.Templates.get("tpl_…")

Errors

Every call raises typed errors so you can branch on the failure (auth, not-found, conflict, transient, timeout). Transient errors are retried automatically; the rest surface to you. See the package’s typed exceptions and the examples/ directory in the SDK for end-to-end patterns.