Python
The Python compile path is a managed runtime β you write a handler function and the platform packs your source, pip-installs your dependencies, and wraps an HTTP server around it. The artifact is small and interpreted, so cold starts are fast. The platform owns the HTTP server, the listening port, and the readiness probe; you only write the handler.
Handler contract
Expose a top-level function named handler:
def handler(payload: bytes, ctx: dict) -> Anypayloadis the raw POST body asbytes. It is not auto-parsed β parse it yourself, e.g.json.loads(payload).ctxis a plaindict(see Context).- The return value is encoded by type (see Input & output).
A minimal real handler (modeled on code_sources/python-hello/handler.py):
import json
from datetime import datetime, timezone
def handler(payload, ctx):
# The runtime passes the raw body. Decode + parse JSON ourselves.
try:
event = json.loads(payload) if payload else {}
except (TypeError, ValueError):
event = {}
name = event.get("name", "world")
return {
"greeting": f"Hello, {name}!",
"execution_id": ctx.get("execution_id", ""),
"function_id": ctx.get("function_id", ""),
"received_at": datetime.now(timezone.utc).isoformat(),
}Context
ctx is a plain dict with exactly three keys:
| Key | Description |
|---|---|
execution_id | This invocationβs ID. |
function_id | This appβs ID, in org/name form. |
organization_id | The owning organizationβs ID. |
Read them with ctx.get("execution_id", "") or ctx["execution_id"].
Input & output
The body arrives as raw bytes in payload; nothing is parsed for you. The return value is encoded by its type:
| Return type | Encoding |
|---|---|
bytes | sent as-is |
str | encoded as UTF-8 |
| anything else | passed through json.dumps(...) |
If the handler raises, the runtime returns HTTP 500 with a JSON body of the form `{error, type, traceback}`.
Dependencies
Declare third-party packages in a requirements.txt at the archive root. The python-deps compiler runs pip install against it and bundles the result into the artifact.
These packages are pre-installed and always available without declaring them:
cloudpickle, numpy, pandas, requests, httpx, pydantic, boto3.
Project layout
Ship either a single file or an archive (zip / tar.gz):
- The top-level
handlermust live inhandler.pyat the archive root. - A bare
handler.pyworks as a single-file upload; add arequirements.txtalongside it (so it must be an archive) when you have custom dependencies.
Override the defaults via environment variables: IGNITE_ENTRY_MODULE (default handler) selects the module, IGNITE_ENTRY_FN (default handler) selects the function.
Logging
The runtime uses stderr for its own output. Your print() to stdout is fine and is captured as logs.
What it compiles to
A tar.gz artifact. Python is interpreted, so there is no native build β the source, your pip-installed dependencies, and the HTTP launcher are packed together and run on a python:3.12 base image. Toolchain: Python 3.12.
Deploy
dodil ignite app create hello --runtime python
dodil ignite draft save org:hello --code ./handler.py
dodil ignite draft publish org:hello
dodil ignite invoke org:hello -p '{"name": "world"}'Python is interpreted, so there is no separate dodil ignite draft compile step β publish snapshots the draft straight into an immutable version.
See also
- Code & Runtimes β the compile vs image paths
- Rust compile contract
- Go compile contract
- Deno compile contract
- Container images β bring or build your own container
- Quickstart