Skip to main content

py-runner

License: AGPL-3.0-or-later Python >=3.10 TestPyPI Docs

Persistent Python code runner: string in, JSON out. A lightweight, dependency-free, ipykernel-like execution library — no Jupyter server, no ZMQ, no required third-party packages.

📖 Full documentation: https://rightfix.github.io/py-runner-docs/

Persistent Python code runner: string in, JSON out. A lightweight, dependency-free, ipykernel-like execution library — no Jupyter server, no ZMQ, no required third-party packages.

from py_runner import Kernel

k = Kernel()
k.execute("x = 40 + 2")
print(k.execute("x + 1"))
# {"output": null,
#  "display": [{"type": "text/plain", "data": "43"}],
#  "error": null, "execution_count": 2, "execution_time": 0.0001}

Install

pip install py-runner-kernel

Requires Python >= 3.10. Zero runtime dependencies.

Quickstart

from py_runner import Kernel, execute, execute_json

# Module-level shared kernel
execute("import math")
print(execute_json("math.sqrt(16)"))

# Isolated session kernel (one per user/request)
k = Kernel(on_input=lambda prompt: "bob", max_history=100)
r = k.execute('name = input("who? ")\nname.upper()')
assert r["display"][0]["data"] == "'BOB'"

Each result is a JSON-serializable dict:

key value
output captured stdout (str | None)
display rich values ([{type, data}]: text/plain, text/html, image/png base64, …)
error traceback / warning text (str | None)
execution_count incrementing cell number
execution_time seconds (float)

Features

  • Persistent namespace with Jupyter-style _, __, ___ and bounded Out[N] history
  • Last-expression display — DataFrames as HTML, arrays/tensors summarized, matplotlib figures as PNG, trailing ; suppresses output
  • Magics: %time, %timeit, %who/%whos, %run, %pip, !shell, %reset
  • Long runs: timeout=, cooperative interrupt(), on_stream chunks, on_heartbeat for silent fit() loops, tqdm \r collapsing, logging/warnings capture
  • Sandboxing: allow_shell=False, allow_pip=False, set_address_space_limit(mb) (Unix), reset(keep_imports=True)
  • CLI: py-runner -c "1+1", py-runner script.py, ... | py-runner, with --timeout, --no-shell, --no-pip

CLI

py-runner -c "print(2 + 3)"
py-runner analysis.py --timeout 300 > result.json
cat cell.py | py-runner
python -m py_runner -c "1+1"

Notebook GUI

py-runner lab --port 8000 --dir ./notebooks

JupyterLab-like notebook editor at http://localhost:8000: file browser, code/markdown cells, run-all/interrupt, rich outputs, per-notebook isolated sessions. Run it from an activated virtualenv and executed code sees that env's libraries — the kernel pill shows the active prefix. Files are jailed to --dir; localhost only.

Project structure

py_runner/
├── __init__.py   # public API: Kernel, execute, execute_json, reset, main
├── kernel.py     # persistent execution kernel (threaded, timeouts, input)
├── magics.py     # %time, %pip, !shell, … (sandbox-flaggable)
├── display.py    # rich display collector (pandas/numpy/PIL/matplotlib)
├── streams.py    # thread-routed streaming stdout, tqdm \r handling
└── utils.py      # guarded imports, address-space limit helper

Development

uv sync            # create .venv
uv run python -c "from py_runner import execute; print(execute('1+1'))"
uv build           # wheel + sdist in dist/
uv publish --publish-url https://test.pypi.org/legacy/  # trial run

HTTP server

py-runner-serve --host localhost --port 8000 --max-sessions 100
S=$(curl -s -X POST localhost:8000/sessions | python3 -c "import sys,json; print(json.load(sys.stdin)['session_id'])")
curl -s -X POST localhost:8000/execute \
  -d "{\"session_id\":\"$S\",\"code\":\"x = 40 + 2\"}"
curl -s -X POST localhost:8000/execute \
  -d "{\"session_id\":\"$S\",\"code\":\"x + 1\"}"        # display: 43 (state kept)
curl -s -X POST localhost:8000/interrupt \
  -d "{\"session_id\":\"$S\"}"
curl -s localhost:8000/sessions                          # list live sessions
curl -s -X DELETE localhost:8000/sessions/$S             # destroy session

Sessions are server-generated UUIDs, live until deleted (no idle timeout), and isolated per ID. Kernels default to allow_shell=false, allow_pip=false; pass {"allow_shell": true} to POST /sessions to relax per session.

License

AGPL-3.0-or-later — see LICENSE. Note the network clause (§13): if you serve a modified version over a network, you must offer its source to those users.

Metadata

Release files for py-runner-kernel 0.1.3

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

Source distribution (sdist)

Source distribution for py-runner-kernel 0.1.3
File Size Uploaded Provenance Actions
py_runner_kernel-0.1.3.tar.gz 200.2 kB Without provenance Details for py_runner_kernel-0.1.3.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for py-runner-kernel 0.1.3
File Interpreter ABI Platform Actions
py_runner_kernel-0.1.3-py3-none-any.whl Python 3 none any Details for py_runner_kernel-0.1.3-py3-none-any.whl

Total release size: 394.9 kB

Release files / py_runner_kernel-0.1.3.tar.gz

Download URL py_runner_kernel-0.1.3.tar.gz
Size 200.2 kB
Tags Source
SHA-256 checksum
How to use checksums
e78649ac1eff9838b6a3247705523579f73d76c1f1635dcf18e10e200ededaa1
BLAKE2b-256 checksum
How to use checksums
837f893b6bca5e0250b6620bbe77b5db9df98e0f623271c610784abd47528937
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / py_runner_kernel-0.1.3-py3-none-any.whl

Download URL py_runner_kernel-0.1.3-py3-none-any.whl
Size 194.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f143418764b9c16463b8167adb1e5cdd8c86434d5645267a14586a8e8a8ca293
BLAKE2b-256 checksum
How to use checksums
683e5cc2924f5a3638d6589ff841da73a9170e46546768a4d2b4493e4c3b2fad
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for py-runner-kernel 0.1.3

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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