Skip to main content

zan

A Flask-compatible Python web framework powered by a Rust HTTP core.

from zan import Flask, jsonify, request

app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello, World!"

@app.route("/user/<int:uid>")
def user(uid):
    return jsonify(uid=uid, name=f"user{uid}")

@app.route("/post", methods=["POST"])
def post():
    return jsonify(echo=request.get_json())

if __name__ == "__main__":
    app.run()   # zan/0.1.0 — Rust HTTP server

Replace from flask import ... with from zan import ... and the rest of your code stays the same.

License: MIT PyPI Python 3.8+ Rust 1.75+

中文 README

Install

zan provides pre-built wheels for Windows, macOS, and Linux. No Rust toolchain is required:

pip install zan

Optional template support:

pip install zan[templates]

To build from source, see Building from source below.

Building from source

You need the Rust toolchain (rustc 1.75+) and Python 3.8+:

python -m venv .venv && source .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install maturin pytest jinja2
maturin develop --release
pytest tests/ -q

Features

  • Drop-in Flask replacement — same Flask, request, session, g, current_app, jsonify, url_for, abort, Blueprint, render_template, and send_file APIs.
  • Rust HTTP core — multi-threaded Tokio server with keep-alive, chunked transfer, pipelining, 100-continue, and size/timeouts enforced in Rust.
  • Trie router — Werkzeug-compatible converters (<int>, <float>, <path>, <uuid>, <any(a,b)>), strict-slash and merge-slash redirects, automatic HEAD/OPTIONS handling.
  • Static files served in Rust — no GIL contention; includes Last-Modified/304, MIME inference, and path-traversal protection.
  • Sessions & flashes — signed cookie sessions (HMAC-SHA256, itsdangerous semantics) and flash/get_flashed_messages.
  • Signals & hooksbefore_request, after_request, teardown_request, teardown_appcontext, context processors, and a full signal implementation.
  • Multiple apps & multi-core — run several apps in the same process (start/stop) and scale beyond the GIL with run(processes=N) plus a Rust TCP load balancer.

Installation & Build

You need the Rust toolchain (rustc 1.75+) and Python 3.8+:

python -m venv .venv && source .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install maturin pytest jinja2
maturin develop --release
pytest tests/ -q

Templates are optional and require jinja2 (pip install jinja2). If jinja2 is not installed, render_template* will raise a clear error.

Flask Compatibility

API surface already implemented and tested (91 test cases):

Category Coverage
Application Flask(import_name), route/add_url_rule, run, start/stop (non-blocking multi-instance), test_client, config, debug, secret_key, logger, cli, extensions, name
Routing <string>, <int>, <float>, <path>, <uuid>, <any(a,b)> converters, methods, endpoint, strict-slash 308 redirect, merge-slashes redirect, automatic HEAD/OPTIONS, 405 + Allow
Request request.args/form/values/json/data/get_json/headers/cookies/method/path/url/endpoint/view_args/blueprint/remote_addr/user_agent/authorization, multipart file uploads
Response str/bytes/dict/list/Response/(body, status, headers) tuples, generators, make_response, jsonify (sorted keys + ensure_ascii), redirect, send_file, set_cookie/delete_cookie
Hooks before_request, after_request, teardown_request, teardown_appcontext, context_processor
Errors Full HTTPException family, abort, errorhandler (status codes and exception classes), debug traceback page
Context request/session/g/current_app proxies, app_context/request_context/test_request_context, RuntimeError when accessed outside context
Session Signed-cookie sessions (HMAC-SHA256, itsdangerous semantics), flash/get_flashed_messages
Blueprints Blueprint, url_prefix, blueprint-level routes/hooks/error handlers, bp.endpoint naming
Templates render_template, render_template_string, blueprint template folders, url_for/get_flashed_messages context injection
URL building url_for (args, _anchor, _external, blueprint defaults)
Static files /static/ served directly from Rust (Last-Modified/304, MIME inference, path-traversal protection)
Signals Full signal support (uses blinker if available, otherwise a built-in compatible implementation)
Multi-instance Multiple apps can start()/stop() in the same process, sharing the Rust runtime
Multi-core run(processes=N) multi-process + Rust TCP load balancer (round-robin, X-Forwarded-For)

Known differences (intentional or not yet implemented):

  • No Werkzeug reloader — in debug mode you must restart manually after code changes (a warning is printed).
  • Not WSGI-based — apps run on the built-in Rust server, not werkzeug.serving or gunicorn.
  • request.scheme is always http (TLS is on the roadmap).

Performance

Local comparison on Windows, Python 3.13, 8 keep-alive connections, pure Python view functions:

Scenario zan Flask dev server Speedup
Plain text 3205 req/s 291 req/s 11.0x
JSON 2941 req/s 423 req/s 6.9x
Route params 3077 req/s 419 req/s 7.4x
POST JSON 2375 req/s 422 req/s 5.6x

TechEmpower-style benchmark (six canonical endpoints, single connection, Flask side served by waitress):

Test zan Flask Speedup
plaintext 1,150 req/s 199 req/s 5.8x
json 1,077 req/s 232 req/s 4.6x
db / queries / fortunes 1.1–1.2x (SQLite-bound)

Multi-core: run(processes=N) breaks through the GIL; CPU-bound views scale almost linearly (2 cores measured at ~1.9x).

To reproduce: python benchmarks/bench_keepalive.py (keep-alive), benchmarks/tfb/harness2.py (TechEmpower, methodology and limitations in benchmarks/tfb/results.md), and benchmarks/bench_multiprocess2.py (multi-core). Note that the Flask dev server (Werkzeug) does not enable keep-alive by default; both frameworks were measured with the same client and workload.

Architecture

┌─────────────────────────────────────────────────────┐
│ Your code (written exactly like Flask)               │
├─────────────────────────────────────────────────────┤
│ zan Python layer (app/wrappers/ctx/session/...)     │  ← compatibility: Flask API aligned one-to-one
├──────────────────────── PyO3 ───────────────────────┤
│ zan Rust core (_zan)                                 │
│  • Process-wide shared Tokio runtime                 │
│    (workers = CPU cores, reused across instances)    │
│  • Multi-threaded Tokio HTTP/1.1 server              │
│    (keep-alive, chunked, pipelining, 100-continue,   │
│     timeouts and size limits)                        │
│  • Trie router (Werkzeug converter semantics,        │
│    static-first, strict/merge-slash redirects)       │
│  • Static file serving (fully in Rust, no GIL)       │
│  • Native Rust JSON serialization                    │
│    (output aligned with json.dumps)                  │
│  • TCP load balancer (multi-process mode,            │
│    round-robin + X-Forwarded-For)                    │
│  • Fast error paths: 404/405/413/431 skip Python     │
└─────────────────────────────────────────────────────┘
  • Each request is parsed by a Tokio worker; after routing it crosses into Python via spawn_blocking (releasing the GIL via allow_threads), with full app/request context pushed so hooks, signals, and sessions behave like Flask.
  • When a view returns str/bytes/dict/tuple, serialization happens in Rust; Response objects pass through FFI as a (status, headers, body) tuple via _fast(), with no intermediate environ.
  • Uncaught exceptions fall back to the Python error chain (errorhandlerHTTPException → 500); debug mode renders a traceback page.

Project Structure

src/            Rust core
  router.rs     Trie router + converters
  http.rs       Connection/parsing/static files/dispatch
  json.rs       Native JSON serialization
  pyapi.rs      PyO3 Server class (shared runtime/lifecycle/load-balancer entry)
  balancer.rs   Multi-process TCP load balancer
zan/            Python compatibility layer (16 modules)
tests/          91 test cases (compatibility 62 / features 18 / multi-method rules 3 / multi-instance & multi-core 8)
blog/           Full blog example (zan backend + React/shadcn frontend served in one process)
benchmarks/     Benchmarks: keep-alive comparison / multi-core scaling / TechEmpower standard (tfb/)

Documentation

Full documentation is currently available in Chinese under docs/:

  • Index — overview, feature table, quick start
  • Quick start — routes, requests, responses, templates, sessions, blueprints, error handling
  • Routing — all converters, methods, strict-slash 308, 405, OPTIONS/HEAD
  • Request object — all request attributes and methods
  • Response object — view return values, jsonify, redirect, send_file, cookies
  • Context & hooksrequest/session/g/current_app, hooks, signals
  • Sessions & flashes — signed cookie internals, permanent sessions, flash
  • Blueprints — registration, url_prefix, blueprint hooks/static/template folders
  • Error handlingHTTPException family, abort, errorhandler
  • Debugging — debug page, reloader, colored output
  • CLIpython -m zan run/shell/routes
  • Config reference — all configuration keys
  • Multi-instance & multi-corestart/stop, processes=N, load balancer
  • Architecture — Rust core, PyO3 boundary, request lifecycle, performance data
  • Testingtest_client, test_request_context, pytest integration
  • FAQ — differences from Flask, deployment advice, performance tuning

English translations of the docs are welcome — see CONTRIBUTING.md.

Roadmap

  • HTTPS/TLS (rustls) and HTTP/2
  • WebSocket support
  • More edge-case behavior for url_for with external and SERVER_NAME
  • CI matrix for platforms other than Windows and abi3 wheel publishing

Contributing

Contributions are welcome! Please read CONTRIBUTING.md for guidelines on bug reports, feature requests, and pull requests.

License

MIT © 2026 RaysunKR

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

zan-0.1.0.tar.gz (395.4 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

zan-0.1.0-cp38-abi3-win_amd64.whl (529.6 kB view details)

Uploaded CPython 3.8+Windows x86-64

zan-0.1.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (611.6 kB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ x86-64

zan-0.1.0-cp38-abi3-macosx_11_0_arm64.whl (567.1 kB view details)

Uploaded CPython 3.8+macOS 11.0+ ARM64

File details

Details for the file zan-0.1.0.tar.gz.

File metadata

  • Download URL: zan-0.1.0.tar.gz
  • Upload date:
  • Size: 395.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for zan-0.1.0.tar.gz
Algorithm Hash digest
SHA256 eebb12c9e7bb7d5d4acb545a7e628a3d2920ec5423675850f69bf34fd6bb8be3
MD5 b851dd9d6c81c18a23361812cc25f991
BLAKE2b-256 d7b4da5d191f11b710e277b2527f12f8bcc4e60ff8d79e0641605d1edbb9ed8b

See more details on using hashes here.

Provenance

The following attestation bundles were made for zan-0.1.0.tar.gz:

Publisher: publish.yml on RaysunKR/zan

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file zan-0.1.0-cp38-abi3-win_amd64.whl.

File metadata

  • Download URL: zan-0.1.0-cp38-abi3-win_amd64.whl
  • Upload date:
  • Size: 529.6 kB
  • Tags: CPython 3.8+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for zan-0.1.0-cp38-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 0b59c36affb0fa8124296137bf1a47963664672fe317bbe7d8831fa4699ff121
MD5 61e7c52d75c62146419dde206dc41730
BLAKE2b-256 49e220589e293ff9272414482564352c4ea4c528d741968fe25cabc4da642c51

See more details on using hashes here.

Provenance

The following attestation bundles were made for zan-0.1.0-cp38-abi3-win_amd64.whl:

Publisher: publish.yml on RaysunKR/zan

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file zan-0.1.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for zan-0.1.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 d196b96b102fc3b0dd0c05cf589f4ecb01d0dd2131b3729090a7a62b994e24a1
MD5 20c0f818198544eb22e94b637da0a75f
BLAKE2b-256 0a3e40b01fe320d60af64f5f9d297aa8e2c34f5c177749db81442b0dbee8d64c

See more details on using hashes here.

Provenance

The following attestation bundles were made for zan-0.1.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: publish.yml on RaysunKR/zan

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file zan-0.1.0-cp38-abi3-macosx_11_0_arm64.whl.

File metadata

  • Download URL: zan-0.1.0-cp38-abi3-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 567.1 kB
  • Tags: CPython 3.8+, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for zan-0.1.0-cp38-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ae853e1248362f2b71621120ab5d58ee09d094ad653197e7b1a47e234c71f11f
MD5 2d7c3f05564c7899c1a7bf29495075e9
BLAKE2b-256 07d86c2a595ca36cd6f004e568571e38b6a0a5a814524b64f751c005a33678cd

See more details on using hashes here.

Provenance

The following attestation bundles were made for zan-0.1.0-cp38-abi3-macosx_11_0_arm64.whl:

Publisher: publish.yml on RaysunKR/zan

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.0 This release

4 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page