Feature
A Python SDK with two decorators
Load your model once, handle jobs one after the other. runqy-python turns a plain Python script into a worker process, with no framework to learn and no config file in your code.
pip install runqy-python
A complete worker
# main.py
import torch
from diffusers import StableDiffusionXLPipeline
from runqy_python import load, task, run
@load
def setup():
pipe = StableDiffusionXLPipeline.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0",
torch_dtype=torch.float16,
).to("cuda")
return {"pipe": pipe}
@task
def generate(payload, ctx):
image = ctx["pipe"](payload["prompt"]).images[0]
url = upload(image) # your storage
return {"url": url}
if __name__ == "__main__":
run()@load Runs once when the process starts. Load models, open connections; the return value becomes ctx.
@task Runs for each job with its JSON payload and ctx. Return a dict for the result; raise to fail and retry.
@reload Optional. Reloads configuration between tasks when the worker receives config-reload, without reloading models.
run() / run_once() run() keeps the process alive and loops over tasks. run_once() handles one task per process.
Two execution modes
long_running
One process stays alive and handles every task. The model loads once. Built for GPU inference: image generation, LLMs, embeddings.
one_shot
A fresh process per task, with run_once(). Nothing leaks from one job to the next.
Built for scripts, scraping and conversions.
Enqueue from Python
The same package ships a client for your application. Other languages use the REST API.
from runqy_python import RunqyClient
client = RunqyClient("https://runqy.example.com", api_key="client-key")
task = client.enqueue("images.premium", {"prompt": "a fox in the snow"})
result = client.get_task(task.task_id)
print(result.state, result.result)
# Many jobs in one request
client.enqueue_batch("images.standard", [{"prompt": p} for p in prompts])Not only Python
Under the SDK is a small protocol: the worker writes one JSON task per line to your process's stdin and reads one JSON response per line from its stdout. Any program that speaks it can be a runqy worker, in Go, Node.js or anything else.
← {"status": "ready"}
→ {"task_id": "abc123", "payload": {"prompt": "a fox"}}
← {"task_id": "abc123", "result": {"url": "..."}, "error": null, "retry": false}