Launch, monitor, and clean up detached external processes with on-disk status tracking (no broker or worker required).
Project description
ox_proc
Launch, monitor, and clean up detached external processes with simple on-disk status tracking — no message broker, no persistent worker process.
ox_proc is aimed at the common case where a short-lived caller
(e.g., a Flask/gunicorn request handler) needs to kick off a
long-running command, return immediately, and let any later process
check progress, read recent output, fetch the final result, or kill
the run.
How it works
Each launch gets a run ID like myslug-20260611T143022-a1b2 and a
run directory:
<base_dir>/<slug>/<run_id>/
status.json written by the launcher; finalized by observers
messages.jsonl appended by the child via post_message()
result.json written by the child via write_result()
stdout.log child's stdout
stderr.log child's stderr
The child is launched in its own session (setsid), so it survives
the launcher's exit. Liveness checks verify both the PID and the
process creation time recorded at launch, so a reused PID is never
mistaken for the original process. No file locking is needed:
status.json and result.json use atomic write-and-rename, and
messages.jsonl is append-only.
Quick start
Launcher side (e.g., in a web request handler):
import ox_proc
run_id = ox_proc.launch(
["python", "-m", "myproject.analysis", "--full"],
slug="analysis",
description="Nightly full analysis",
env_updates={"ANALYSIS_MODE": "full"},
max_live=1, # raise TooManyLiveError if one is running
)
Child side (inside the launched command):
import ox_proc
ox_proc.post_message("loading data", progress=0.1)
...
ox_proc.write_result({"rows": 12345, "ok": True}) # always on success
Status side (any process, any time):
info = ox_proc.get_info(run_id)
info["state"] # "running", "finished", "died", or "killed"
info["messages"] # recent post_message() records
info["stdout_tail"] # last lines of stdout
info["result"] # contents of result.json, or None
ox_proc.count_live() # {"analysis": 1, ...}
ox_proc.kill_run(run_id)
ox_proc.cleanup() # call periodically: kills over-runtime runs,
# deletes expired finished runs
Conventions and caveats
- Always call
write_result()on success. Because the child is detached, its true exit code is lost; a dead process with noresult.jsonis reported as state"died". - End times are observed: recorded when an observer first notices the process is gone. TTL-based deletion counts from that time, with a backstop (default 24 h from launch) for runs whose end was never observed.
- Live runs are killed by
cleanup()once they exceed their per-runmax_runtime_seconds(default 8 h; passNonefor unlimited). kill_run()sends SIGTERM to the whole process group; there is no SIGKILL escalation.- The default base directory is
tempfile.gettempdir()/ox_proc-<username>, which the OS may purge (reboots, tmpfiles cleaning) — run history is not durable. Passbase_dir=everywhere for a durable location. - POSIX only (relies on sessions/process groups and atomic appends).
- The
max_livelimit is best-effort: two simultaneous launches can race past it.
Installation
pip install ox_proc
Requires Python 3.9+ and psutil.
Development
pip install -e ".[dev]"
pytest
To build for pypi, first build via
pip install --upgrade build twine
python -m build
and then push to test pypi via:
twine upload --repository testpypi dist/*
and finally if that looks good you can upload to the production pypi via
twine upload dist/*
Project details
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 ox_proc-0.1.2.tar.gz.
File metadata
- Download URL: ox_proc-0.1.2.tar.gz
- Upload date:
- Size: 9.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
156fa0070bb2754f52fc039af29caccf79da60dd5e7ce9c51d4a6355d15b8a63
|
|
| MD5 |
6e5fddd89095e401d23f858acd12adb7
|
|
| BLAKE2b-256 |
cbd473a62eee3b39667fbc01b0ba63531793fd1cdd100819bba102794d7f8b85
|
File details
Details for the file ox_proc-0.1.2-py3-none-any.whl.
File metadata
- Download URL: ox_proc-0.1.2-py3-none-any.whl
- Upload date:
- Size: 9.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
94020810a96194890c7c69fdacb021792e1f9a96706ca7470534911b7da5902d
|
|
| MD5 |
13be444014c95bc92598c1ad345eece7
|
|
| BLAKE2b-256 |
4f7a43ea8a15ea7dfef43dad7660908859750fb934c4fed4d4fbe330342a1231
|