patx/micropie
Official Hg Mirror of MicroPie - an ultra-micro ASGI Python web framework that gets out of your way.
$ hg clone https://hglab.io/hg/patx/micropie
Introduction
MicroPie is a fast, lightweight, modern Python web framework built on ASGI for asynchronous web applications. Designed for flexibility and simplicity, it enables high-concurrency web apps with built-in WebSockets, session management, middleware, lifecycle event handling, and optional template rendering. Extensible for integration with ASGI-compatible tools like python-socketio and ServeStatic, it’s inspired by CherryPy and licensed under the BSD 3-Clause License.
Key Features
- 📬 Routing: Automatic mapping of URLs to functions with support for dynamic and query parameters.
- 🔑 Sessions: Simple, pluggable session management using cookies.
- 🎨 Templates: Jinja2, if installed, for rendering dynamic HTML pages.
- 🚧 Middleware: Support for custom request middleware enabling functions like rate limiting, authentication, logging, and more.
- 💨 Real-Time Communication: Built-in WebSocket support for real-time, bidirectional communication.
- ☀️ ASGI-Powered: Built with asynchronous support for modern web servers like Uvicorn, Hypercorn, and Daphne, enabling high concurrency.
- ☁️ Lightweight Design: Only optional dependencies for flexibility and faster development/deployment.
- 👶 Lifecycle Events: ASGI lifespan event handling for startup and shutdown tasks (e.g., database initialization).
- 🏁 Competitive Performance: Check out how MicroPie compares to other popular ASGI frameworks below!
Useful Links
- Homepage: patx.github.io/micropie
- Official Documentation: micropie.readthedocs.io
- PyPI Page: pypi.org/project/MicroPie
- GitHub Project: github.com/patx/micropie
- File Issue/Request: github.com/patx/micropie/issues
- Example Applications: github.com/patx/micropie/tree/main/examples
- Introduction Lightning Talk: Introduction to MicroPie on YouTube
Latest Release Notes
View the latest release notes here. It is useful to check release notes each time a new version of MicroPie is published. Any breaking changes (rare, but do happen) also appear here.
Table of Contents
- Installing MicroPie
- Getting Started
- Core Features
- Learn by Examples
- Comparisons
- Benchmark Results
- Suggestions or Feedback?
Documentation Roadmap
- Tutorials: quick start, routing, and websockets.
- How-to Guides: Practical recipes for sessions, middleware, streaming, and more.
- Reference: Full API docs for App, Request, WebSocket, and related classes.
- What’s New: Version-by-version highlights at What's new in MicroPie.
Installing MicroPie
Installation Profiles
Install whichever profile fits your use case:
| Profile | Command | Includes |
|---|---|---|
| Minimal | pip install micropie |
Core framework only |
| Standard | pip install micropie[standard] |
Core + jinja2 + multipart |
| All | pip install micropie[all] |
Standard + orjson + uvicorn |
If you are just getting started, use standard:
pip install micropie[standard]
For an ultra-minimal setup, you can also use the standalone script (development version):
Place it in your project directory and you are ready to go. Install optional packages only if needed:
pip install jinja2 multipart
Use jinja2 for _render_template and multipart for multipart file/form parsing.
By default MicroPie will use the json library from Python's standard library. If you need faster performance you can use orjson. MicroPie will use orjson if installed by default. If it is not installed, MicroPie will fallback to json. This means with or without orjson installed MicroPie will still handle JSON requests/responses the same. To install orjson and take advantage of its performance, use:
pip install orjson
Install an ASGI Web Server
In order to test and deploy your apps you will need an ASGI web server like Uvicorn, Hypercorn, or Daphne.
If you installed micropie[all] Uvicorn should be ready to use. If you didn't install all of MicroPie's optional dependencies, use:
pip install uvicorn
Getting Started
Create Your First ASGI App
Save the following as app.py:
from micropie import App
class MyApp(App):
async def index(self):
return "Welcome to MicroPie ASGI."
app = MyApp()
Run the server with:
uvicorn app:app
Access your app at http://127.0.0.1:8000.
Core Features
Route Handlers
MicroPie's route handlers map URLs to methods in your App subclass. Handler input can come from automatic argument binding or request helper methods.
Key Points
- Automatic Mapping: URLs map to method names (e.g.,
/greet→greet,/→index). - Private Methods: Methods starting with
_(e.g.,_private_method) are private and inaccessible via URLs, returning 404. Security Note: Use_for sensitive methods to prevent external access. - Automatic Argument Binding: Handler args are populated from path/query/body data by parameter name.
- Request Helpers:
self.request.query(name, default)for query-string values.self.request.form(name, default)for form/body values.self.request.json()for full JSON payloads, orself.request.json(name, default)for a key lookup.- HTTP Methods: Handlers support all methods (GET, POST, etc.). Check
self.request.methodto handle specific methods. - Responses:
- String, bytes, or JSON-serializable object.
- Tuple:
(status_code, body)or(status_code, body, headers). - Sync/async generator for streaming.
Advanced Usage
- Custom Routing: Use middleware for explicit routing (see examples/middleware and examples/explicit_routing).
- Errors: Auto-handled 404/400; customize via middleware.
- Dynamic Params: Use
*argsfor multiple path parameters.
Automatic Argument Binding
MicroPie can bind handler parameters directly from incoming request data:
class MyApp(App):
async def greet(self, name="Guest"):
return f"Hello, {name}!"
async def submit(self, username="Anonymous"):
return f"Submitted by: {username}"
Access:
- http://127.0.0.1:8000/greet/Alice returns Hello, Alice!.
- http://127.0.0.1:8000/greet?name=Alice also returns Hello, Alice!.
- POST application/x-www-form-urlencoded to /submit with username=bob returns Submitted by: bob.
- POST application/json to /submit with {"username": "bob"} also returns Submitted by: bob.
Helper-Based Request Access
Use helper methods for query, form, and JSON payload access:
class MyApp(App):
async def greet(self):
name = self.request.query("name", "Guest")
return f"Hello, {name}!"
async def submit(self):
username = self.request.form("username", "Anonymous")
return f"Submitted by: {username}"
async def submit_json(self):
data = self.request.json()
username = self.request.json("username", "Anonymous")
return {"submitted_by": username, "raw": data}
Access:
- http://127.0.0.1:8000/greet?name=Alice returns Hello, Alice!.
- POST application/x-www-form-urlencoded to /submit with username=bob returns Submitted by: bob.
- POST application/json to /submit_json with {"username": "bob"} returns JSON including submitted_by: "bob".
By default, MicroPie's route handlers can accept any request method. Check self.request.method in a handler when route behavior differs by method. For lower-level request internals such as query_params, body_params, and get_json, see docs/apidocs/reference/request.rst.
Lifecycle Event Handling
MicroPie supports ASGI lifespan events, allowing you to register asynchronous handlers for application startup and shutdown. This is useful for tasks like initializing database connections or cleaning up resources.
Key Points
- Startup Handlers: Register async handlers to run during
lifespan.startupusingapp.startup_handlers.append(handler). - Shutdown Handlers: Register async handlers to run during
lifespan.shutdownusingapp.shutdown_handlers.append(handler). - Error Handling: Errors during startup or shutdown are caught and reported via
lifespan.startup.failedorlifespan.shutdown.failedevents. - Use Cases: Ideal for setting up database pools, external service connections, or logging systems on startup, and closing them on shutdown.
Example
from micropie import App
async def setup_db():
print("Setting up database...")
# DB init code here
print("Database setup complete!")
async def close_db():
print("Closing database...")
# DB close code here
print("Database closed!")
class MyApp(App):
async def index(self):
return "Welcome to MicroPie ASGI."
app = MyApp()
app.startup_handlers.append(setup_db)
app.shutdown_handlers.append(close_db)
On startup, the setup_db method initializes the database connection. On shutdown (e.g., Ctrl+C), the close_db method closes it.
Real-Time Communication with WebSockets and Socket.IO
MicroPie includes built-in support for WebSocket connections. WebSocket routes are defined in your App subclass using methods prefixed with ws_, mirroring the simplicity of MicroPie's HTTP routing. For example, a method named ws_chat handles WebSocket connections at ws://<host>/chat.
MicroPie’s WebSocket support allows you to:
- Define WebSocket handlers with the same intuitive automatic routing as HTTP (e.g.,
/chatmaps tows_chatmethod). - Access query parameters, path parameters, and session data in WebSocket handlers, consistent with HTTP requests.
- Manage WebSocket connections using the WebSocket class, which provides methods like
accept,receive_text,send_text, andclose.
Check out a basic example:
from micropie import App
class Root(App):
async def ws_echo(self, ws):
await ws.accept()
while True:
msg = await ws.receive_text()
await ws.send_text(f"Echo: {msg}")
app = Root()
Use Socket.IO for Advanced Real-Time Features
If you want more advanced real-time features like automatic reconnection, broadcasting, or fallbacks (e.g., polling), you can integrate Socket.IO with your MicroPie app using Uvicorn as the server. See examples/socketio for integration instructions and examples.
Jinja2 Template Rendering
Dynamic HTML generation is supported via Jinja2. This happens asynchronously using Python's asyncio library, so make sure to use async and await with this method.
app.py
class MyApp(App):
async def index(self):
return await self._render_template("index.html", title="Welcome", message="Hello from MicroPie!")
templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ title }}</title>
</head>
<body>
<h1>{{ message }}</h1>
</body>
</html>
Static File Serving
MicroPie does not natively support static files, if you need them, you can easily implement it in your application code or integrate dedicated libraries like ServeStatic or Starlette’s StaticFiles alongside Uvicorn to handle async static file serving. Check out examples/static_content to see this in action.
Streaming Responses
Support for streaming responses makes it easy to send data in chunks.
class MyApp(App):
async def stream(self):
async def generator():
for i in range(1, 6):
yield f"Chunk {i}\n"
return generator()
Sessions and Cookies
Built-in session handling simplifies state management:
class MyApp(App):
async def index(self):
if "visits" not in self.request.session:
self.request.session["visits"] = 1
else:
self.request.session["visits"] += 1
return f"You have visited {self.request.session['visits']} times."
You also can use the SessionBackend class to create your own session backend. You can see an example of this in examples/sessions.
Middleware
MicroPie allows you to create pluggable middleware to hook into the request lifecycle. Take a look at a trivial example using HttpMiddleware to send console messages before and after the request is processed. Check out examples/middleware to see more.
from micropie import App, HttpMiddleware
class MiddlewareExample(HttpMiddleware):
async def before_request(self, request):
print("Hook before request")
async def after_request(self, request, status_code, response_body, extra_headers):
print("Hook after request")
class Root(App):
async def index(self):
print("Hello, World!")
return "Hello, World!"
app = Root()
app.middlewares.append(MiddlewareExample())
Middleware provides an easy and reusable way to extend the MicroPie framework. We can do things such as rate limiting, checking for max upload size in multipart requests, explicit routing, CSRF protection, and more.
MicroPie apps can be deployed using any ASGI server. For example, using Uvicorn if our application is saved as app.py and our App subclass is assigned to the app variable we can run it with:
uvicorn app:app --workers 4 --port 8000
Learn by Examples
The best way to get an idea of how MicroPie works is to see it in action! Check out the examples folder for more advanced usage, including: - Template rendering - Custom HTTP request handling - File uploads - Serving static content - Session usage - JSON Requests and Responses - Socket.io Integration - Async Streaming - Middleware including explicit routing and more - Form handling and POST requests - WebSockets - Lifecycle event handling - URL shortener app (live demo @ erd.sh) - And more
Comparisons
Features vs Other Popular Frameworks
| Feature | MicroPie | Flask | CherryPy | Bottle | Django | FastAPI |
|---|---|---|---|---|---|---|
| Routing | Automatic | Manual | Automatic | Manual | Views | Manual |
| Template Engine | Jinja2 (Opt.) | Jinja2 | Plugin | SimpleTpl | Django | Jinja2 |
| Middleware | Yes | Yes | Yes | Yes | Yes | Yes |
| Session Handling | Plugin | Plugin | Built-in | Plugin | Built-in | Plugin |
| Async Support | Yes | No | No | No | Yes | Yes |
| Built-in Server | No | No | Yes | Yes | Yes | No |
| Lifecycle Events | Yes | No | Yes | No | Yes | Yes |
Benchmark Results
The table below summarizes the performance of various ASGI frameworks based on a 15-second wrk test with 4 threads and 64 connections, measuring a simple "hello world" JSON response. Learn More.
| Framework | Requests/sec | Avg Latency (ms) | Max Latency (ms) | Transfer/sec (MB) | Total Requests | Data Read (MB) |
|---|---|---|---|---|---|---|
| Starlette | 21615.41 | 3.00 | 90.34 | 2.93 | 324374 | 43.93 |
| MicroPie | 18519.02 | 3.53 | 105.00 | 2.84 | 277960 | 42.68 |
| FastAPI | 8899.40 | 7.22 | 56.09 | 1.21 | 133542 | 18.08 |
| Quart | 8601.40 | 7.52 | 117.99 | 1.17 | 129089 | 17.60 |
Suggestions or Feedback?
We welcome suggestions, bug reports, and pull requests!
- File issues or feature requests here.
- Security issues that should not be public, email harrisonerd [at] gmail.com.
Rock Your Powered by MicroPie Badge
You can add a Powered by MicroPie badge to your projects README using the following markdown:
[](https://patx.github.io/micropie)
© 2025 Harrison Erd
