Skip to content

Running BlackBull

BlackBull has three entry points, in increasing order of how "production-shaped" they are. All three resolve to the same underlying serve() function — pick whichever shape fits the deployment surface.

1. app.run(...) — in-Python, single command

# Single-worker, plain HTTP/1.1 on :8000
app.run(port=8000)

# HTTPS + HTTP/2 via ALPN on :8443
app.run(port=8443, certfile='cert.pem', keyfile='key.pem')

# Multi-worker (pre-forks N workers; master holds the listening sockets)
app.run(port=8443, certfile='cert.pem', keyfile='key.pem', workers=4)

# Development: hot-reload when *.py files change
# Requires the [reload] extra: pip install 'blackbull[reload]'
app.run(port=8000, reload=True)

app.run() is synchronous — it internalises asyncio.run so callers write app.run(port=8000) rather than asyncio.run(app.run(...)). reload=True and workers > 1 both trigger the master-process path (long-lived supervisor around the worker pool).

Full signature:

def run(port=None, certfile=None, keyfile=None,
        workers=None, unix_path=None, inherited_fd=None,
        max_connections=None, stream_queue_depth=None,
        ws_queue_depth=None, reload=None, reload_paths=None):
    ...

Each argument left unset (None) falls back to the value declared on the bound AppConfig (if any), then to serve()'s built-in default. Declaring the settings once keeps __main__ to a single line:

from blackbull import BlackBull, AppConfig

app = BlackBull(config=AppConfig(port=8443, certfile='cert.pem',
                                 keyfile='key.pem', workers=4))

if __name__ == '__main__':
    app.run()

2. blackbull CLI — useful for systemd, Docker, PaaS

# Same flags as app.run kwargs
blackbull myapp:app \
    --bind 0.0.0.0:8443 \
    --certfile cert.pem --keyfile key.pem \
    --workers 4

# Auto-reload via the CLI
blackbull myapp:app --bind 127.0.0.1:8000 --reload

The CLI accepts any module:attribute import path; the attribute may be a BlackBull instance or a plain ASGI callable. See blackbull --help for the full flag list and Configuration for how flags compose with environment variables and TOML config files.

blackbull serve — zero-code static files

To serve a directory of static files without writing any application code — a drop-in upgrade over python -m http.server, with ETag, HTTP/2 (under TLS), and a directory index built in:

blackbull serve ./public --bind :8080
blackbull serve ./public --certfile cert.pem --keyfile key.pem  # HTTPS + HTTP/2

See Static files → blackbull serve.

3. Any external ASGI 3.0 server

BlackBull instances are valid ASGI 3.0 callables, so they work under any ASGI server:

uvicorn myapp:app --port 8000
hypercorn myapp:app --bind 0.0.0.0:8000
granian --interface asgi myapp:app

You lose BlackBull's own HTTP/2 frame layer and WebSocket codec (the surrounding server's protocol stack handles framing instead), but the application code is portable as-is.

Embedded use under an existing event loop

To run BlackBull inside an existing event loop, or to pre-bind a socket before forking a test subprocess, instantiate ASGIServer directly:

import asyncio
from blackbull.server import ASGIServer

server = ASGIServer(app, certfile='cert.pem', keyfile='key.pem')
server.open_socket(8443)
await server.run()

open_socket(port=0) binds to a kernel-assigned port and exposes it as server.port — the same pattern the testing fixture uses.

Picking the deployment shape

Shape When
python myapp.py (calls app.run()) Development, one-shot scripts, tutorial-style apps
blackbull myapp:app … systemd, Docker, PaaS — anywhere the deployment surface is a CLI
External ASGI server When the surrounding deployment dictates uvicorn / granian / hypercorn for tooling reasons
ASGIServer direct Embedded inside another asyncio program, or when fine-grained socket / TLS control is needed (e.g. mTLS — see TLS)

Next

  • Workers — pre-fork multiprocessing, uvloop, abuse defences, production checklist.
  • TLS — HTTPS, HTTP/2 via ALPN, self-signed certs, mTLS.
  • Behind nginx — terminating TLS upstream, trusted-proxy headers.
  • Unix and fd inheritanceAF_UNIX, systemd socket activation.
  • Hot reload--reload for development.