Run code in fast, isolated cloud sandboxes — zero Metaflow dependency
Project description
sandrun
Run Python functions and scripts in isolated sandboxes — locally or in the cloud.
Two ways to use it
1. CLI — run a script
sandrun run script.py
sandrun run --backend daytona --package requests script.py
sandrun run --backend e2b --cpu 4 --memory 8192 train.py -- --epochs 10
Your current directory is packaged and shipped to the sandbox. Output streams back in real time. Exit code propagates to the shell.
PEP 723 inline script metadata is supported automatically. If your script declares dependencies in a # /// script block, sandrun reads them without any --package flags:
# /// script
# dependencies = [
# "requests>=2.28",
# "numpy",
# ]
# ///
import requests, numpy
...
sandrun run script.py # dependencies installed automatically
Extra --package flags are merged and deduplicated with inline deps.
2. Decorator — call a function remotely
from sandrun import daytona
@daytona(packages=["httpx"])
def fetch(url: str) -> str:
import httpx
return httpx.get(url).text
html = fetch.remote("https://example.com") # runs in a Daytona sandbox
html = fetch("https://example.com") # runs locally, unchanged
fn.remote() dispatches to the sandbox. fn() is the original function — unit tests work without touching any sandbox.
Backends
| Backend | Install | Requires | Cold start |
|---|---|---|---|
boxlite |
sandrun[boxlite] |
KVM or HVF (local) | ~1–2s |
daytona |
sandrun[daytona] |
DAYTONA_API_KEY |
<100ms |
e2b |
sandrun[e2b] |
E2B_API_KEY |
~150ms |
pip install sandrun[boxlite] # local microVM, no API key
pip install sandrun[daytona] # export DAYTONA_API_KEY=...
pip install sandrun[e2b] # export E2B_API_KEY=...
SANDRUN_BACKEND sets the default backend for both the CLI and decorator.
CLI
sandrun run [OPTIONS] SCRIPT [ARGS...]
--backend, -b NAME boxlite (default), daytona, e2b
--package, -p PKG pip package to install (repeatable)
--cpu N CPUs (default: 1)
--memory MB memory in MB (default: 1024)
--gpu SPEC GPU spec (backend-specific)
--env, -e KEY=VALUE environment variable (repeatable)
--timeout SEC timeout in seconds (default: 300)
--image IMAGE sandbox image override
Arguments after SCRIPT are forwarded to the script. Use -- to separate sandrun flags from script flags:
sandrun run -b daytona -e API_KEY=secret script.py -- --verbose --output out.csv
Also works as a module: python -m sandrun run script.py
Decorator
from sandrun import sandbox, daytona, e2b, boxlite
@daytona(
packages=["requests", "numpy"], # pip packages to install
cpu=2,
memory=4096,
gpu="T4",
env={"API_KEY": "..."},
timeout=600,
streaming=True, # print sandbox stdout in real time
)
def my_func(x: int) -> float:
...
result = my_func.remote(42) # sandbox
result = my_func(42) # local
@sandbox(backend="daytona") is the generic form. @daytona, @e2b, @boxlite are shorthands. All three decorator forms work:
@daytona # no parens
@daytona() # empty parens
@daytona(packages=["numpy"]) # with options
Exceptions raised inside the sandbox propagate locally with their original type.
How it works
Both the CLI and decorator package your working directory with TarballStager, upload arguments via backend.upload(), execute a generated runner script, and retrieve output via backend.download(). No extra dependencies — stdlib only.
The backend interface is a thin abstraction over each provider's SDK: create, exec, upload, download, destroy. You can use it directly for scripting or custom pipelines:
from sandrun.backends import get_backend
backend = get_backend("daytona")
sandbox_id = backend.create()
result = backend.exec_script_streaming(
sandbox_id,
"python -c \"print('hello')\"",
on_stdout=print,
)
backend.destroy(sandbox_id)
Development
git clone https://github.com/npow/sandrun
cd sandrun
pip install -e ".[dev]"
pytest
ruff check .
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sandrun-0.1.2.tar.gz.
File metadata
- Download URL: sandrun-0.1.2.tar.gz
- Upload date:
- Size: 35.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2f7686201bbf824c1d306a535fadc95699bdf621322f287e0c3c2815b0730d0e
|
|
| MD5 |
dc50e2bb89a65e4ec618f44cb6843eab
|
|
| BLAKE2b-256 |
2e5478e364bf2cb3b3a3edb5cdb9fabcdab325c3c5b6a8cc7af82674d866f865
|
Provenance
The following attestation bundles were made for sandrun-0.1.2.tar.gz:
Publisher:
publish.yml on npow/sandrun
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sandrun-0.1.2.tar.gz -
Subject digest:
2f7686201bbf824c1d306a535fadc95699bdf621322f287e0c3c2815b0730d0e - Sigstore transparency entry: 1059249314
- Sigstore integration time:
-
Permalink:
npow/sandrun@eaffbb6f8242c6e0799013139d49371de580590a -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/npow
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@eaffbb6f8242c6e0799013139d49371de580590a -
Trigger Event:
push
-
Statement type:
File details
Details for the file sandrun-0.1.2-py3-none-any.whl.
File metadata
- Download URL: sandrun-0.1.2-py3-none-any.whl
- Upload date:
- Size: 37.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
86113817a6e79b9797b6b6ed339acb23c96f71c3420f7f2e445d6aa3f90ef1a8
|
|
| MD5 |
885bb28cdbe7a32a0be6e0483a5e3100
|
|
| BLAKE2b-256 |
e09081707c8986910ab89c022b8502e3845461cfb809e34bf974bededd95e94a
|
Provenance
The following attestation bundles were made for sandrun-0.1.2-py3-none-any.whl:
Publisher:
publish.yml on npow/sandrun
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sandrun-0.1.2-py3-none-any.whl -
Subject digest:
86113817a6e79b9797b6b6ed339acb23c96f71c3420f7f2e445d6aa3f90ef1a8 - Sigstore transparency entry: 1059249316
- Sigstore integration time:
-
Permalink:
npow/sandrun@eaffbb6f8242c6e0799013139d49371de580590a -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/npow
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@eaffbb6f8242c6e0799013139d49371de580590a -
Trigger Event:
push
-
Statement type: