Skip to main content

safe-py-runner

A lightweight Python code runner with guardrails for LLM agent workflows.

GitHub Repository

Why This Package

When building agents that execute generated Python code, you often choose between:

  1. Running code directly in your process (exec) - risky.
  2. Full container sandboxing - heavier and slower.
  3. External sandbox APIs - added cost and latency.

safe-py-runner provides a practical middle path:

  • subprocess isolation
  • timeout enforcement
  • memory limits (POSIX; macOS enforcement can be weaker than Linux)
  • import/builtin policy restrictions
  • JSON-safe input/output handling

Honest scope:

  • Good fit: LLM-generated scripts for your own team and other controlled internal workloads.
  • Not good alone: anonymous public code execution. Use Docker/VM/OS sandboxing as the primary boundary.

Where It Fits

Option Isolation Strength Operational Cost Typical Use
eval / exec in main process Low Low Local scripts, trusted experiments
safe-py-runner Medium Low to medium Internal tools, agent prototypes, controlled workloads
Docker / VM / E2B-style sandbox High Medium to high Production multi-tenant or hostile untrusted code

Production guidance:

  • For hostile public-user code, use Docker/VM/external sandboxing as the primary boundary.
  • safe-py-runner can be used as an extra inner guardrail layer.

It supports two policy modes:

  • restrict (default): block selected symbols.
  • allow: allow only selected symbols.

Backends

The API now uses explicit engine objects through run_code(..., engine=...).

  • LocalEngine: host subprocess execution in managed venv.
  • DockerEngine: managed Docker container execution.

If DockerEngine is used but Docker is unavailable, execution fails with a clear error. DockerEngine can also target remote daemons with docker_context or SSH options.

Docker installation:

For production workloads, prefer DockerEngine over LocalEngine.

Installation

pip install safe-py-runner

Quick Start

from safe_py_runner import LocalEngine, RunnerPolicy, run_code

policy = RunnerPolicy(
    timeout_seconds=5,
    memory_limit_mb=128,
    blocked_imports=["os", "subprocess", "socket"],
)

engine = LocalEngine(venv_dir="/tmp/safe_py_runner_pypi_demo")

result = run_code(
    code="import math\nresult = math.sqrt(input_data['x'])",
    input_data={"x": 81},
    policy=policy,
    engine=engine,
)

# Or load policy from a TOML config file
result = run_code(
    code="result = 1 + 1",
    policy_file="/absolute/path/to/policy.toml",
    engine=engine,
)

if result.ok:
    print(result.result)  # 9.0
else:
    print(result.error)

Security Note

This is not an OS-level sandbox.
For untrusted hostile code, use container/VM isolation in addition to this package.

Memory-limit caveat: RLIMIT_AS is platform-dependent. On macOS, address-space limits may not behave as strictly as Linux.

Common Gotchas

  1. engine is required for run_code(...); there is no implicit backend selection.
  2. policy and policy_file are mutually exclusive; pass only one.
  3. In allow mode, allowed_globals controls both input key injection and extra_globals.
  4. importlib is intentionally blocked in all modes.
  5. Package environments require pinned specs (name==version).

More Information

Metadata

Release files for safe-py-runner 0.1.7

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for safe-py-runner 0.1.7
File Size Uploaded
safe_py_runner-0.1.7.tar.gz 58.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for safe-py-runner 0.1.7
File Interpreter ABI Platform
safe_py_runner-0.1.7-py3-none-any.whl Python 3 none any Details

Total release size: 85.0 kB

Release files / safe_py_runner-0.1.7.tar.gz

Download URL safe_py_runner-0.1.7.tar.gz
Size 58.1 kB
Tags Source
SHA-256 checksum
How to use checksums
1153384884a3e1e4bf0e59f0ab4dcbd19639eebbda550949c33dab6304293887
BLAKE2b-256 checksum
How to use checksums
128932df97bb5de1d0f973a0ef6ff7289d81dc44f57ce9c0157d297abdcd9e0f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Feb 26, 2026.

Transparency log

Release files / safe_py_runner-0.1.7-py3-none-any.whl

Download URL safe_py_runner-0.1.7-py3-none-any.whl
Size 27.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9699089926aafe058bbcb6a76cdacdae8fdfc3961ab130f27a964aa4e3528b02
BLAKE2b-256 checksum
How to use checksums
ec7834911e39f66620ee496f5d8d2167d9005babedd984466b47d6aebb1547f9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Feb 26, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.7 This release

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page