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.4

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.4
File Size Uploaded Provenance Actions
py_runner_kernel-0.1.4.tar.gz 201.7 kB Without provenance Details for py_runner_kernel-0.1.4.tar.gz

Built distribution (wheel)

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

Total release size: 397.1 kB

Release files / py_runner_kernel-0.1.4.tar.gz

Download URL py_runner_kernel-0.1.4.tar.gz
Size 201.7 kB
Tags Source
SHA-256 checksum
How to use checksums
0311f741f81d94a98c6db3c74c77f2db865b6220cf098edf12084e6f3bd8868c
BLAKE2b-256 checksum
How to use checksums
affb8eeeaac6ea2ecf9ab0faf3d668839cfedcc19f180f974f56e1318f3b60c2
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.4-py3-none-any.whl

Download URL py_runner_kernel-0.1.4-py3-none-any.whl
Size 195.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
21b8e170c2af2b86448c92ce5858c0a73662f631c6f66cb28e661d3db6b25fed
BLAKE2b-256 checksum
How to use checksums
374b4d227ffea2e6472937f5b9adafc64f5df6500ae4beab00b4fba0fde010af
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.4

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