https://blog.miguelgrinberg.com/post/microdot-yet-another-python-web-framework miguelgrinberg.com * Home * My Courses and Books * Consulting * About Me * + Light Mode + Dark Mode + ------------------------------------------------------------- + System Default * RSS Feed Twitter Mastodon GitHub YouTube LinkedIn Patreon Microdot: Yet Another Python Web Framework Posted by [Miguel Grinberg] on 2023-12-26T12:43:35Z under [Python] [Programming] [Microdot] [MicroPython] I just realized that I have never written on this blog about Microdot , my very own web framework for Python. I have released Microdot 2.0 a few days ago, so I guess this is a good time to make a belated announcement, and tell you why this world needs yet another Python web framework. But before I tell you about the reasons and the history of Microdot, let me share some of its features: * Flask-like syntax, but without the magical/obscure parts (no application/request contexts) * Small enough to work with MicroPython, while also being compatible with CPython * Fully compatible with asyncio * Websocket support * Server-Sent Events (SSE) support * Templating support with Jinja (CPython) and uTemplate (MicroPython) * Cross-Origin Request Sharing (CORS) support * User sessions stored on cryptographically signed cookies * Uses its own minimal web server on MicroPython, and integrates with any ASGI or WSGI web servers on CPython * Included test client to use in unit tests Interested? Keep reading to learn more about Microdot. Why Microdot Back in 2019, I was working on a hardware project based on the ESP8266 microcontroller. For the software portion of this project I used MicroPython, an alternative implementation of the Python language that is designed for small devices. I wanted to host a small web-based interface on the device, and to my surprise I could not find any usable web frameworks. Things such as Flask or Bottle do not work under MicroPython because they are too big for it. The only MicroPython web framework I could find was one called "picoweb", which required an unofficial fork of the MicroPython language, which to me was a deal breaker. Microdot was born out of needing to have a web framework that was as close as possible to Flask, but designed to run on an official and actively maintained version of MicroPython. I ended up creating Microdot, and used it to complete my project. I also put the source code on GitHub, since it was obvious to me that there was a hole in the MicroPython ecosystem in terms of web frameworks. While it has received growing attention from hardware inclined developers, it managed to stay below the radar for a lot of people in the Python community for almost 5 years now. Here is a timeline of the major events in Microdot's history: Date Event April 2019 Microdot 0.1, first public release August Microdot 1.0, with a synchronous base implementation and 2022 an asyncio extension December Microdot 2.0, redesigned as 100% asynchronous 2023 How Does Microdot Code Look Like? Microdot is actually very similar to Flask. You write web routes as decorated functions: from microdot import Microdot app = Microdot() @app.get('/') async def index(request): return {'hello': 'world'} app.run(debug=True) The @app.get decorator is used to define GET requests. There are similar decorators for POST, PATCH, PUT and DELETE. Like Flask, Microdot handles OPTIONS and HEAD requests automatically. Microdot 2 is asynchronous, so it is best to write handler functions as async def functions. Under CPython, regular def functions execute in a thread executor (like FastAPI), but most hardware devices that run MicroPython lack threading support, so regular functions on that platform just block for as long as they run. One aspect in Flask that I do not like is the use of application and request contexts, as these add an unnecessary layer of complexity. I did not want to have that, so request handler functions in Microdot just receive a request object as a first positional argument. As with Flask, the return value from a handler function is the response, and Microdot automatically formats the response as JSON if a dictionary is returned. It also supports second and third returned values for custom status code and headers. Microdot also copies the way streamed responses work in Flask with the use of generators, and also supports asynchronous generators. I like the functionality offered by Blueprints in Flask, but here once again I feel Flask makes everything too complicated. In Microdot, you can create multiple application instances and use the mount() method to combine them: api = Microdot() @api.get('/users') async def get_users(): pass main_app = Microdot() main_app.mount(api, url_prefix='/api') # /api/users route is added to main_app Microdot has native support for WebSocket and Server-Sent Events. Here are example endpoints that use these features: from microdot.websocket import with_websocket from microdot.sse import with_sse @app.route('/echo') @with_websocket async def echo(request, ws): while True: data = await ws.receive() await ws.send(data) @app.route('/events') @with_sse async def events(request, sse): for i in range(10): await asyncio.sleep(1) await sse.send({'counter': i}) Hopefully there is nothing mysterious or magical in this code and you can understand it fully just from reading it. If you want to render HTML templates, Microdot can use Jinja or uTemplate, the latter being the main (only?) templating library available for MicroPython. Templates can be rendered synchronously (blocking the asyncio loop) or asynchronously. For larger templates it is best to use the async interface as that improves concurrency. Templates can also be streamed as regular or asynchronous generators, one more way to improve performance and concurrency. User sessions are implemented in a way that is also similar to Flask, but I decided to write user sessions as JWTs, which are fairly easy to debug. If you want to learn more about Microdot's features, I have written documentation for it. I also offer a nice collection of examples in the GitHub repository. How Small is Microdot? This is not a straightforward question to answer, because unlike Flask, FastAPI and most other frameworks, Microdot has a modular structure, so there are a number of different configurations that can be measured depending on what features are used. When working with CPython this is not very important, but for MicroPython projects running on microcontrollers it is useful to be able to pick and choose exactly what you need and drop the parts that you don't. The core Microdot framework comes in a single microdot.py Python source file. Below I used the cloc utility to count how many lines of code the current version of this file has: files blank comment code Microdot 2.0.1 (minimal) 1 216 456 728 Next I calculated the full Microdot configuration for the same version, including all of its features: files blank comment code Microdot 2.0.1 (full) 11 435 759 1577 Just so that you have an idea of how small this is, let's see how big Flask and FastAPI are. To make this a more consistent comparison, I've included Werkzeug with Flask, and Starlette with FastAPI. files blank comment code Flask 3.0.0 24 1775 3211 3854 Werkzeug 3.0.1 59 4043 5634 11704 Total 83 5818 8845 15558 files blank comment code FastAPI 0.106.0 40 2052 5884 9839 Starlette 0.27.0 34 1008 477 4969 Total 74 3060 6361 14808 From this you can see that both Flask and FastAPI, when combined with their main supporting dependency have about 15K lines of code each, while Microdot has 1.5K or roughly 10% of the size of its bigger competitors (or 5% if you only need basic web routing features). Since I'm counting Werkzeug and Starlette as part of Flask and FastAPI respectively, you may be curious about what third-party dependencies Microdot relies on, and if there are any big ones. The single-file minimal version does not require any dependencies at all, and it even includes its own web server. Some of the optional features do require third-party dependencies, and this is comparable to the larger frameworks. Like Flask, you will need to add a templating library (Jinja or uTemplate) to use templates. For user sessions, Microdot relies on PyJWT, while Flask uses its own Itsdangerous package. Should I Switch to Microdot? For a MicroPython project I think Microdot is a great framework to use, even though there are now a couple others that did not exist back in 2019. If you are using CPython you are certainly welcome to switch if you want to, but my recommendation would be to stay with your current web framework if you are happy with it. A good reason to switch would be if you want to make better use of your server's resources. It's really hard to make predictions, but depending on the project you may be able to fit an extra web server worker or two on the same hardware, just from RAM savings after switching from a larger framework to Microdot. But as I said, I wouldn't go through the pain of a migration unless size is very important to you. What I would like to ask is that you keep Microdot in mind for when you start a new project. If you end up using it, I would like to know how it works for you, so please reach out! Become a Patron! Hello, and thank you for visiting my blog! If you enjoyed this article, please consider supporting my work on this blog on Patreon! [patreon-bu] Share this post: Hacker News Reddit Twitter LinkedIn Facebook E-Mail 6 comments * [88dd48c006] #1 Moses Koroma said 2023-12-27T13:23:53Z I will like to explore the technology * [38a7647f9c] #2 Sean Mayorga said 2023-12-27T13:45:30Z This is awesome! Thanks for sharing with the world I'm going to use the heck out of this * [fcc9a2b463] #3 Nick Antonaccio said 2023-12-27T21:25:00Z I'm looking forward to trying this out, thank you! * [45566d896a] #4 Donald KANTI said 2023-12-27T23:40:40Z Great technology Thanks for sharing * [dd5c77c4e3] #5 Shahrukh said 2023-12-28T16:15:23Z Would the flask packages like flask-alchemy and forms work with microdot too? * [729e26a2a2] #6 Miguel Grinberg said 2023-12-28T20:29:06Z @Shahrukh: No, there is no connection between Flask and Microdot. If you need database support for Microdot you can use Alchemical. Microdot includes its own basic form handling. * <<<< * << * >> * >>>> Leave a Comment Name [ ] Email [ ] Comment [ ] Captcha [Submit] MicroPython for the Raspberry Pi Pico W MicroPython for the Raspberry Pi Pico W If you like my MicroPython tutorial series on this blog, you may also like my MicroPython for the Raspberry Pi Pico W book. Click here to get this Book! About Miguel [miguel] Welcome to my blog! I'm a software engineer and technical writer, currently living in Drogheda, Ireland. You can also find me on Twitter, Mastodon, Github, LinkedIn, YouTube, Facebook and Patreon. Thank you for visiting! Categories AI RSS Feed [AI] 1 AWS RSS Feed [AWS] 1 Arduino RSS Feed [Arduino] 7 Authentication RSS Feed [Authentication] 10 Blog RSS Feed [Blog] 1 C++ RSS Feed [C++] 5 CSS RSS Feed [CSS] 1 Cloud RSS Feed [Cloud] 10 Database RSS Feed [Database] 22 Docker RSS Feed [Docker] 5 Filmmaking RSS Feed [Filmmaking] 6 Flask RSS Feed [Flask] 126 Games RSS Feed [Games] 1 Heroku RSS Feed [Heroku] 1 IoT RSS Feed [IoT] 8 JavaScript RSS Feed [JavaScript] 35 MicroPython RSS Feed [MicroPython] 9 Microdot RSS Feed [Microdot] 1 Microservices RSS Feed [Microservices] 2 Movie Reviews RSS Feed [Movie Reviews] 5 OpenStack RSS Feed [OpenStack] 1 Personal RSS Feed [Personal] 3 Photography RSS Feed [Photography] 7 Product Reviews RSS Feed [Product Reviews] 2 Programming RSS Feed [Programming] 186 Project Management RSS Feed [Project Management] 1 Python RSS Feed [Python] 168 REST RSS Feed [REST] 7 Rackspace RSS Feed [Rackspace] 1 Raspberry Pi RSS Feed [Raspberry Pi] 8 React RSS Feed [React] 18 Robotics RSS Feed [Robotics] 6 Security RSS Feed [Security] 12 Video RSS Feed [Video] 22 WebSocket RSS Feed [WebSocket] 2 Webcast RSS Feed [Webcast] 3 Windows RSS Feed [Windows] 1 (c) 2012- by Miguel Grinberg. All rights reserved. Questions?