Top 9 Asynchronous Web Frameworks For Python
Top 9 Asynchronous Web Frameworks For Python
com
Ankush
18–23 minutes
Tornado
Surprisingly, Tornado isn’t a new framework at all. Its initial release was in 2009
and since then, its focus has been on providing rock-solid asynchronous
programming with high concurrency.
Sanic
Sanic is a “modern” framework in the true sense of the word: it doesn’t support
Python version below 3.6, supports the simple and universal async/await syntax
out of the box, and as a result, doesn’t make you read loads of documentation
and keep edge cases in your mind before you can write your first HTTP
handler.
Vibora
Vibora is a close cousin of Sanic, except that it’s fixated on becoming the fastest
Python web server out there. In fact, the very first visit of its website greets you
with a framework comparison:
As you can see, Vibora claims to be several times faster than the classic
frameworks and being more than twice as fast as Sanic, its nearest competitor.
Of course, benchmarks are to be taken with a grain of salt. �
Although in syntax and features, Vibora is comparable to Sanic (or maybe even
slightly better as it bundles popular libraries and things like templating are
available out of the box), I’d consider Sanic to be more mature as it’s been
around longer and has a bigger community.
If you’re a performance junkie, though, Vibora might float your boat. That said,
as of writing Vibora is underdoing a complete rewrite to become even faster,
and the link to its performance version says it’s under “heavy development.” It’s
going to be a let down for those who picked up Vibora earlier and soon must
face breaking changes, but hey, it’s early days in Python async world, and
nobody expects things to be stable.
Quart
If you enjoy developing in Flask but rue the lack of async support, you’ll enjoy
Quart a lot.
Quart is compliant with the ASGI standard, which is a successor to the famous
WSGI standard and offers async support. The interesting thing about Quart is
that it’s not only similar to Flask but is actually compliant with the Flask API!
The author of this framework wanted to preserve the Flask feel and just add
async, WebSockets, and HTTP 2 support to it. As a result, you can learn Quart
right from the Flask documentation, just keeping in mind that functions in Quart
are asynchronous.
Feels (almost) exactly like Flask, doesn’t it?!
Since Quart is an evolution of Flask, all the features inside Flask are available:
routing, middleware, sessions, templating, blueprints, and so on. In fact, you
can even use Flask extensions directly inside Quart. One catch is that Python
3.7+ is only supported, but, then, if you’re not running the latest version of
Python, maybe async isn’t the right path. �
The documentation is really wanting if you don’t have earlier experience with
Flask, but I can recommend Quart as it’s probably the only async framework
nearing its 1.0 release soon.
FastAPI
The last (but most impressive) framework on this list is FastAPI. No, it’s not an
API-only framework; in fact, FastAPI seems to be the most feature-rich and
documentation-rich framework that I came across when researching async
Python frameworks.
It’s interesting to note that the framework author studied several other
frameworks in-depth, from the contemporary ones like Django to modern ones
like Sanic, as well as looking across technologies into NestJS (a Node.js,
Typescript web framework). Their development philosophy and extensive
comparisons can be read here.
The syntax is quite pleasant; one can even argue it’s much more enjoyable
than the other frameworks we’ve come across:
And now, the list of killer features that make FastAPI outshine other
frameworks:
Automatic API doc generation: As soon as your endpoints have been written,
you can play with the API using a standards-compliant UI. SwaggerUI, ReDoc,
and others are supported.
The framework also does automatic data model documentation with JSON
Schema.
Modern development: Yes, the word “modern” gets thrown around a lot, but I
found FastAPI actually to walk its talk. Dependency Injection and type hinting
are first-class citizens, enforcing not just good coding principles but preventing
bugs and confusion in the long run.
Extensive documentation: I don’t know about you, but I’m a total sucker for
good documentation. And in this area, FastAPI wins hands-down. It has pages
upon pages of docs explaining almost every little subtlety and “watch out!”
moments for developers of all levels. I sense a clear “heart and soul” in the
docs here, and the only comparison I can find is the Django docs (yes, FastAPI
docs are that good!).
Beyond the basics: FastAPI has support for WebSockets, Streaming, as well
as GraphQL, besides having all the traditional helpers like CORS, sessions,
cookies, and so forth.
And what about the performance? Well, FastAPI is built on the amazing
Starlette library, resulting in performance that matches Node, and in some
cases, even Go! All in all, I really have the feeling that FastAPI is going to race
ahead as the top async framework for Python.
BlackSheep
BlackSheep can be used to create server-side or full-stack applications with an
MVC pattern.
Some of the features that BlackSheep offers are
• A rich-code API.
• Built-in dependency injection.
• Built-in generation of OpenAPI documentation.
• Automatic binding of request handlers.
Project Setup
Let’s create a basic server-side application with BlackSheep. Quickly run the
below commands one by one to set up the project.
We are done with setting up the project. Let’s create a file called server.py
and place the following code.
We have created our most famous hello world application. There is only one
route with HTTP GET method for now, and it’s /. The function home is called
request handler in BlackSheep.
We have used a router decorator from the app. There is another way to create
routes i.e.., route. We will be using the router in this tutorial. You can find
more about route in the docs.
Let’s run the application with the following command.
Go to the http://localhost:8000/ in the browser. You will see hello world in
the browser. Let’s talk a bit about the command that we used to run the
application.
• We have used uvicorn package to run our application.
• The server is the file name that we have given. If you use a different file name,
change it in the start command as well.
• The option --port is give the port on which our app should run.
• Finally, the --reload option is to reload the application in the browser
whenever we make changes to the server file.
JSON Response
In the real world, we need the API responses in JSON in most cases. We can
return a JSON response from the method by wrapping the JSON object with
json from the blacksheep package. Let’s see how we can do it.
We have imported json from the blacksheep and wrapped the JSON object
with it. Check it in the browser for JSON response.
Route Parameters
We need to accept the route params sometimes for the requests. We can do it
in BlackSheep by defining them inside the HTTP method. Let’s see it.
We are accepting one route parameter called name. Go to the
http://localhost:8000/Geekflare. The method will return a greeting with
the name given in the route.
The router decorator will pass the parameter with the same name to the home
function as it’s given to the decorator. Here, it will be name. If you change it in
the decorator, change it in the home function as well.
We can accept as many route parameters as possible in a similar way. Let’s see
a quick example.
We have accepted one more route parameter called info. Go to
http://localhost:8000/Geekflare/Chandan to check it.
Query Parameters
Request Object
The only thing left in our basics is checking other HTTP methods. Before going
into it, let’s check the request object for the API.
All the request handlers in the BalckSheep will have a request argument which
contains all the information of the coming request. It includes request headers,
path parameters, query parameters, data, etc..,
Let’s see an example to see the request object.
You can see the following output in the terminal.
We can access different things from the request. You can check the docs for it.
Here, our focus is on the request body. Let’s see how to access the request
body from the request object.
There is a method called json in the request, which will return the data that’s
coming from the request. Pass some data in the API request and call it. You will
see the data printing in the terminal that you have passed to the API.
HTTP Methods
We have seen the GET and POST methods in the above examples. Similarly,
you can use the PUT, DELETE, etc.., methods as well. Trying yourself won’t be
a problem as they are straightforward.
AIOHTTP
aiohttp is another framework that comes with the following key features.
• It supports both server-side and client-side WebSockets.
• It supports both server and client application development.
• Its web server has middleware, signals, and pluggable routing.
Project Setup
Let’s create a basic server-side application with aiohttp. Quickly run the
following commands to set up the project.
Create a file called server.py and place the following code in it.
The web.Application instance is our main application. We have added the
HTTP GET method with the route / which returns our favorite hello world. The
web.run_app function is used to run the application, which takes the
web.Application instance as an argument.
The function home is called a request handler in aiohttp. And it has one, and
only argument called request, which contains all the information of the
incoming request.
Run the application with the following command. It’s the same as running
normal python programs.
Go to http://localhost:8080/ in the browser. You will see hello world in the
browser.
JSON Response
Route Parameters
We can define the route parameters while adding the routes. And they can be
accessed from the request argument of the request handler. Let’s see an
example.
All route parameters can be accessed from the request.match_info as shown
in the above example. Go to http://localhost:8080/Geekflare to check it.
We can also have regex to match the routes. Let’s say we have to accept only
/{any_number}. We can do it by replacing the '/{name}' with
r'/{number:\d+}'. We have added regex to the path parameter, which will
accept only if the regex is passed.
Let’s see an example
Go to http://localhost:8080/Geekflare, you will 404 error as Geekflare doesn’t
match the regex pattern that we have given. Now, go to
http://localhost:8080/1234567890 you will see the response in the
browser.
Query Parameters
HTTP Methods
We have seen how to create a HTTP GET method in the above examples. We
need to know how to access the request data before moving ahead. Let’s see
an example of it.
In the above example, we have changed the API method from GET to POST.
We have accessed the request data using request.json method.
Make a post request to http://localhost:8080/, you will see the request
data printing in the terminal.
Similarly, you can use the PUT, DELETE, etc.., methods as well. Try them
yourself and have fun.
You can continue exploring more about the framework in their docs.
Falcon
Falcon is an ASGI framework to build REST APIs and microservices. It has the
following key features.
• It supports WebSockets.
• Supports middleware and hooks for request processing.
• Simple and straightforward exception handling.
Project Setup
Let’s set up a project to learn the basics of the falcon framework. Set up the
project with the following commands.
Create a file called server.py and place the following code.
We have created a class with on_get method which is HTTP GET method. The
method has two arguments. One is request and another one if response. You
should have guessed what they are by their names themselves.
The request argument contains all the information of the incoming request
which can be accessed to process the request. And the response argument is
used to send the response by setting different things.
Unlike BlackSheep and AIOHTTP we don’t have to return a response. We can
use the response and set whatever details we need to send as a response. In
the above example, we have set the status to 200, the content type to text, and
the text to hello world.
Run the application with the following command
Go to http://localhost:8000/, you will see the hello world as a response.
JSON Response
We can return the response as JSON by converting the data into JSON using
json.dumps method. Let’s see an example
Go to http://localhost:8000/, you will see the response in JSON.
Route Parameters
The request parameters are passed to the HTTP methods as arguments. You
can see the example below for a better understanding.
The name path parameter will be passed to on_get method as an argument. Go
to http://localhost:8000/Geekflare/ and check the response. We can
have as many route parameters as we want.
Query Parameters
HTTP Methods
We have seen the GET method in the above example. The one thing we need
to know for other methods is how to access request data. We can access the
request data using request.stream.read method. Let’s see an example.
We have added one POST method in which we accessed the request data and
printed it to the terminal after converting it to JSON. Make a POST request with
some data to check the output.
Try adding other HTTP methods like DELETE, PUT, etc.., by yourself. We have
converted only the basics of the falcon framework. But, there is a lot in it. Go
and read the docs to find out more deeply about it.
Starlette
Starlette is a lightweight ASGI framework in Python. It has similar almost all the
basic features to build server-side applications.
Set up the project with the following commands.
Creating APIs with Starlette is similar to what we have seen in the last
frameworks. The syntax and way of creating APIs are different. All the concepts
remain the same. So, we are going to include all the things in a single program.
Create a file called server.py and place the following code.
Run the application with the following command.
Test all things that we have seen in the previous frameworks. You can learn
more about the Starlette framework in its docs.
Conclusion
A lot is going on in the Python async landscape these days. New frameworks
are popping up, old ones are being rewritten, and libraries are being evolved to
match async behavior. While Python has built-in support for an event loop, and
it’s possible to make parts of your application async, you can choose to go all-in
and build on one of the frameworks here.
Just be sure to keep the long-term in mind: several of the Python async
frameworks out there are in the early stages and are being rapidly evolved,
which is going to hurt your development process and raise business costs.
Caution is key!
But all said and done; Python is production-ready to deliver light-out
performance when it comes to web frameworks. If for so long you’ve been
thinking of migrating to Node, now you don’t need to! �
Sounds cool? Master Python today!