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.