py-runner
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 boundedOut[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=, cooperativeinterrupt(),on_streamchunks,on_heartbeatfor silentfit()loops, tqdm\rcollapsing,logging/warningscapture - 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)
| 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)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| 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.