Before you decide on a particular framework, let’s make sure we’re on the same page when it comes to definitions.
What exactly do we have in mind when we talk about a web application framework?
In short, a web framework is a package of generic functionalities that makes creating web apps easier for the developer. It serves as a shortcut that removes the need to write unnecessary code by reusing existing solutions. As a result, it reduces the time your developers need to spend on writing code and makes their work more effective.
Web frameworks can be divided into two categories: frontend and backend. The former, also known as CSS frameworks, is all about the parts of the web app the users see and interact with. The latter relates to the behind-the-scenes aspects of creating a web app.
The crucial benefit of using Python frameworks is that you can mix and match frontend and backend elements within each framework to achieve the desired result. You can either focus on one or merge several of them, depending on the scope of your project.
By offering ready-made solutions, web app frameworks help developers add complex and dynamic elements that would otherwise be very difficult or time-consuming to develop from scratch.
Is using a framework necessary when working with Python? The short answer is: no, it is not necessary.
Of course, you can write in Python without a web development framework. However, using one is extremely useful when building web apps and websites since Python wasn’t written as a direct web scripting language, like PHP was, for example. So common things like connecting to databases aren’t native to it, and frameworks come in handy.
The benefits of using a Python framework include—apart from obviously making it easier to create web applications in Python—working with a more organized code, increased productivity, and a simplified web development process.
Frameworks have libraries for handling common tasks and tools for debugging and testing your apps. With a Python framework, the implementation and integration is easier, the documentation is better, the efficiency increases, and the entire process is more secure, because all the framework libraries are heavily tested.
What’s more, there are communities that develop software using the same code base, so if you have questions, you can easily find help. In summary, if your language has a good framework that’s well-supported by the community, there’s not much reason against using it.
There are obviously some disadvantages to using a Python web framework. Firstly, you are tied to a particular tool, which limits your options for switching to a different one. When working on an existing project, you may also need to refactor your code to work with the web development framework.
Additionally, some of the Python frameworks may not be suitable at all for smaller projects, and others completely incomprehensible for beginners.
Finally, Python web frameworks can take some time to learn and be quite complex. That way, you may not understand how to use individual components of the frameworks due to the large size of some of them and spend too much time getting the hang of it.
Having said that, the disadvantages don’t outweigh the benefits of working with Python web development frameworks. Let’s now consider a couple of things you should know before you choose the right Python framework for you.
Before you make a move and choose a Python web development framework, keep in mind the size and complexity—some can be quite large and significantly challenging to learn.
You should also consider the features that the framework offers, as some offer more extensions and tools than others.
Something that you should also take into account is the documentation available for the framework and the license that it uses; some are open-source software (OSS), while others are closed source software (CSS), which means the software uses proprietary and closely guarded code.
Essentially, we categorize Python frameworks into three types: full-stack (also known as enterprise), microframeworks, and asynchronous (async) frameworks. Before we move on to discussing the best Python web frameworks in 2022, let’s take a closer look at those categories.
If you’re planning to develop a large structure filled with lots of requirements and features, a full-stack framework will be the best choice for you and your project.
Such frameworks are an all-in-one solution for all your requirements. Typically, form generators, form validation, and template layouts, among others, are available within a usual full-stack framework.
On the other hand, if you’re creating a small and simple app, you should rather think about choosing a microframework.
Microframeworks are lightweight and they don’t offer additional functionalities and features, such as database abstraction layer, form validation, and specific tools and libraries. So developers using them will need to add a lot of code and additional requirements manually.
Asynchronous (async) frameworks, which are becoming more and more popular, are a type of microframework that allows handling a large set of concurrent connections. Usually, an async framework built for Python uses the programming language’s asyncio library.
Django is one of the most popular Python frameworks. Offering all the tools you need to build a web application within a single package, from low- to high-end, is its trademark.
Django applications are based on a design pattern similar to MVC, the so-called MVT (Model-View-Template) pattern. Models are defined using the Django ORM, while SQL databases are mainly used as storage.
The framework has a built-in admin panel, allowing for easy management of the database content. With minimal configuration, this panel is generated automatically based on the defined models.
Views can include both functions and classes, and the assignment of URLs to views is done in one location (the urls.py file), so that after reviewing that single file you can learn which URLs are supported. Templates are created using a fairly simple Django Templates system.
Django is praised for strong community support and detailed documentation describing the functionality of the framework. This documentation coupled with getting a comprehensive environment after the installation makes the entry threshold rather low. Once you go through the official tutorial, you’ll be able to do most of the things required to build an application.
Unfortunately, Django’s monolithism also has its drawbacks. It is difficult, though not impossible, to replace one of the built-in elements with another implementation. For example, using some other ORM (like SQLAlchemy) requires abandoning or completely rebuilding such items as the admin panel, authorization, session handling, or generating forms.
Because Django is complete but inflexible, it is suitable for standard applications (i.e. the vast majority of software projects). However, if you need to implement some unconventional design, it leads to struggling with the framework, rather than pleasant programming.
Created in 2007, web2py is a framework originally designed as a teaching tool for students, so the main concern for its authors was ease of development and deployment.
Web2py is strongly inspired by Django and Ruby on Rails, sharing the idea of convention over configuration. In other words, web2py provides many sensible defaults that allow developers to get off the ground quickly.
This approach also means there are a lot of goodies bundled with web2py. You will find everything you’d expect from a web framework in it, including a built-in server, HTML-generating helpers, forms, validators, and many more—nothing unusual thus far, one could argue. Support for multiple database engines is neat, though it’s a pretty common asset among current web frameworks.
However, some other bundled features may surprise you, since they are not present in other frameworks:
The framework proudly claims to be a full-stack solution, providing everything you could ever need.
Web2py has extensive documentation available online. It guides newcomers step by step, starting with a short introduction to the Python language. The introduction is seamlessly linked with the rest of the manual, demonstrating different aspects of web2py in a friendly manner, with lots of code snippets and screenshots.
Despite all its competitive advantages, web2py’s community is significantly smaller than Django’s, or even Pyramid’s. Fewer developers using it means your chances of getting help and support are lower. The official mailing list is mostly inactive.
Pyramid, the third noteworthy Python web framework, is rooted in two other products that are no longer developed: Pylons and repoze.bfg. The legacy left by its predecessors caused Pyramid to evolve into a very mature and stable project.
The philosophies of Pyramid and Django differ substantially. Unlike Django, Pyramid is trivial to customize, allowing you to create features in ways that the authors of the framework themselves hadn’t foreseen. It does not force the programmer to use framework’s idioms; it’s meant to be a solid scaffolding for complex or highly non-standard projects.
Pyramid strives to be persistence-agnostic. While there is no bundled database access module, a common practice is to combine Pyramid with the powerful, mature SQLAlchemy ORM. Of course, that’s only the most popular way to go. Programmers are free to choose whatever practices suit them best, such as using the peewee ORM, writing raw SQL queries, or integrating with a NoSQL database, just to name a few.
All options are open, though this approach requires a bit of experience to smoothly add the desired persistence mechanisms to the project. The same goes for other components, such as templating.
Openness and freedom are what Pyramid is all about. Modules bundled with it relate to the web layer only and users are encouraged to freely pick third-party packages that will support other aspects of their projects.
However, this model causes a noticeable overhead at the beginning of any new project, because you have to spend some time choosing and integrating the tools your team is comfortable with. Still, once you put the effort into making additional decisions during the early stages of the work, you are rewarded with a setup that makes it easy and comfortable to start a new project and develop it further.
Pyramid is a self-proclaimed “start small, finish big, stay finished framework.” This makes it an appropriate tool for experienced developers who are not afraid of playing the long game and working extra hard in the beginning, without shipping a single feature within the first few days. Less experienced programmers may feel a bit intimidated.
With Twisted, Python developers were able to do async programming long before it was cool. Twisted is one of the oldest and most mature Python projects around.
Originally released in 2002, Twisted predates even PEP8, so the code of the project does not follow the famous code style guide recommendations. Admittedly, this may somewhat discourage people from using it these days.
Twisted’s heart is an event-driven networking engine called
reactor. It is used for scheduling and calling user-defined callbacks.
In the beginning, developers had to use explicit callbacks by defining functions and passing them around separately for cases when an operation succeeded and when it failed.
At some point, Twisted introduced inlineCallbacks—the notation for writing asynchronous code that was as simple to read as regular, synchronous code. This solution played very well with Python’s syntax and greatly influenced modern async toolkit from the standard library, asyncio.
The greatest advantage of this framework is that although Twisted itself is just an engine with few bundled extensions, there are many additional extensions available to expand its functionality. They allow for both low-level network programming (TCP/USP) and high, application-level work (HTTP, IMAP, SHH, etc).
This makes Twisted a perfect choice for writing specialized services; however, it is not a good candidate for regular web applications. Developers would have to write a lot of things on their own to get the functionality they take for granted with Django.
Twisted is being actively maintained. There is an undergoing effort to migrate all of its code to be compatible with Python 3. The core functionality was rewritten some time ago, but many third-party modules are still incompatible with newer versions of the interpreter.
This may raise some concerns whether Twisted is the best choice for new projects. On the other hand, though, it is more mature than some asyncio-based solutions. Also, Twisted has been around for quite some time now, which means it will undoubtedly be maintained at least for a good while.
Masonite is a relatively new framework that has been steadily gaining traction among developers. Since its first release in December 2017, it’s amassed over 1,300 stars on GitHub.
It comes with plenty of out-of-the-box functionalities and a highly extendable architecture. Fast and easy to install, Masonite is an MVC and batteries-included framework compatible with Python 3.4+. It’s similar to Django in that it strives to provide everything a web developer might need.
To increase the adoption of the framework among developers, its creator has prioritized ease of use and access to high-quality training materials. Masonite boasts an extensive documentation and plenty of tutorials for both beginner and experienced developers, as well as an active Slack channel.
The framework features over a dozen time-saving commands that allow developers to create views, controllers, job queues, models, and others from the command line.
Other key benefits include Orator, an Active Record-style ORM, as well as a simple routing engine and migration system.
Flask is considered a microframework. It comes with basic functionality, while also allowing for easy expansion. Therefore, Flask works more as the glue that allows you to join libraries with each other.
For example, “pure Flask” does not provide support for any storage, yet there are many different implementations that you can install and use interchangeably for that purpose (such as Flask-SQLAlchemy, Flask-MongoAlchemy, and Flask-Redis). Similarly, the basic template system is Jinja2, but you can use a replacement (like Mako).
The motto of this framework is “one drop at a time,” and this is reflected in its comprehensive documentation. The knowledge of how to build an application is acquired in portions here; after reading a few paragraphs, you will be able to perform basic tasks.
You don’t have to know the more advanced stuff right away—you’ll learn it once you actually need it. Thanks to this, students of Flask can gather knowledge smoothly and avoid boredom, making Flask suitable for learning.
A large number of Flask extensions, unfortunately, are not supported as well as the framework itself. It happens quite often that the plug-ins are no longer being developed or their documentation is outdated. In cases like these, you need to spend some time googling a replacement that offers similar functionality and is still actively supported.
When building your application with packages from different authors, you might have to put quite a bit of sweat into integrating them with each other. You will rarely find ready-made instructions on how to do this in the plug-ins’ documentation, but in such situations the Flask community and websites such as Stack Overflow should be of help.
Bottle is a WSGI-compliant microframework that is fast and lightweight.
One of its main advantages is the single-file distribution process, which makes it easy to share and upload the app. To start coding, all you need to do is download bottle.py into the project directory.
Conveniently, the whole framework fits into one file. And since Bottle doesn’t depend on any external libraries, there is no need to install anything else to access it.
By design, Bottle is flexible, easy to use, and it makes web application development a breeze. However, due to its single-file distribution pattern, the framework is best suited for smaller apps, rather than larger projects.
Falcon is another microframework on our list. The goal of the Falcon project is to create a minimalist foundation for building web apps where the slightest overhead matters.
Authors of the framework claim it is a bare-metal, bloat-free toolkit for building very fast backend code and microservices. Plus, it is compatible with both Python 2 and 3.
A big advantage of Falcon is that it is indeed very fast. Benchmarks published on its website show an incredible advantage over mainstream solutions like Django or Flask.
The downside, though, is that Falcon offers very little to start with. There’s routing, middlewares, hooks—and that’s basically everything. There are no extras: no validation, no authentication, etc. It is up to the developer to extend functionality as needed.
Falcon assumes it will be used for building REST APIs that talk JSON. If that is the case, you really need literally zero configuration. You can just sit down and code.
This microframework might be an exciting proposition for implementing highly-customized services that demand the highest performance possible. Falcon is an excellent choice when you don’t want or can’t invest in asyncio-based solutions.
If you’re thinking, “Sometimes the simplest solution is the best one,” you should definitely consider Falcon.
Have you ever imagined handling 1,000,000 requests per second with Python?
It seems unreal, since Python isn’t the fastest programming language out there. But when a brilliant move was made to add asyncio to the standard library, it opened up countless possibilities.
Japronto is a microframework that leverages some of them. As a result, this Python framework was able to cross the magical barrier of 1 million requests handled per second.
You may still be at a loss as to how that is possible, exactly.
It all comes down to 2 aces up Japronto’s sleeve: uvloop and PicoHTTPParser. Uvloop is an asyncio backend based on libuv, while PicoHTTPParser is a lightweight HTTP headers parser written in C. All core components of the framework are also implemented in C. A wide variety of low-level optimizations and tricks are used to tweak performance.
Japronto is designed for special tasks that could not be accomplished with bloated mainstream frameworks. It is a perfect fit for problems where every nanosecond counts. Knowledgeable developers, obsessed with optimization, will reap all of its possible benefits.
Additionally, Japronto is meant to provide a solid foundation for microservices using REST APIs with minimal overhead. In other words, there’s not much in the box. Developers only need to set up routing and decide which routes should use synchronous or asynchronous handlers.
It might seem counterintuitive, but if a request can be handled in a synchronous way, you shouldn’t try to do it asynchronously, as the overhead of switching between coroutines will limit performance.
What is quite unfortunate is that Japronto is not being actively developed. On the other hand, the project is licensed under MIT, and the author claims he is willing to accept any contributions. Like Sanic, the framework is meant to work with Python 3.5+ versions.
FastAPI allows you to build APIs with Python 3.6 or newer, based on standard Python type hints. As its name suggests, the framework is one of the fastest and most efficient Python web frameworks out there.
Based on Starlette, FastAPI comes with all of its features, including GraphQL support, templates, and others. Since Starlette uses ASGI—the newer standard for asynchronous web frameworks—it also offers some features not available in WSGI frameworks, such as WebSockets or background tasks.
One of the key advantages of FastAPI, besides the development speed, is that it helps minimize code duplication and bugs. The framework is very intuitive; editor support and autocompletion mean less time spent debugging.
FastAPI is also based on and fully compatible with OpenAPI and JSON Schema, the open standards for APIs.
Sanic differs considerably from the aforementioned frameworks because unlike them, it is based on asyncio—Python’s toolbox for asynchronous programming, bundled with the standard library starting from version 3.4.
In order to develop projects based on Sanic, you have to grasp the ideas behind asyncio first. This involves a lot of theoretical knowledge about coroutines, concurrent programming caveats, and careful reasoning about the data flow in the application.
Once you get your head around Sanic/asyncio and applies the framework to an appropriate problem, the effort pays off. Sanic is especially useful when it comes to handling long-living connections, such as WebSockets. If your project requires support for WebSockets or making a lot of long-lasting external API calls, Sanic is a great choice.
Another use case of Sanic is writing a “glue-web application” that can serve as a mediator between two subsystems with incompatible APIs. Note that it requires at least Python 3.5, though.
The framework is meant to be very fast. One of its dependencies is uvloop—an alternative, drop-in replacement for asyncio’s not-so-good built-in event loop. Uvloop is a wrapper around libuv, the same engine that powers Node.js. According to the uvloop documentation, this makes asyncio work 2–4 times faster.
Sanic is a microframework, just like Flask. Apart from routing and other basic web-related goodies like utilities for handling cookies and streaming responses, there’s not much inside. Sanic imitates Flask, for instance by sharing the concept of Blueprints—tiny sub-applications that allow developers to split and organize their code in bigger applications.
Sanic also won’t be a good choice for simple CRUD applications that only perform basic database operations. It would just make them more complicated with no visible benefit.
Aiohttp is another library based on asyncio, the modern Python toolkit for writing asynchronous code. Not meant to be a framework in a strict sense, aiohttp is more of a toolbox, supplementing the async arsenal with everything related to HTTP.
This means aiohttp is helpful not only for writing server applications, but also to clients. Both will benefit from asyncio’s goodies, most of all the ability to handle thousands of connections at the same time, provided the majority of operations involves I/O calls.
Such powerful clients are great when you have to issue many API calls at once, for example for scraping web pages. Without asyncio, you would have to use threading or multiprocessing, which are harder to get right and require much more memory.
Apart from building standalone applications, aiohttp’s clients are a great supplement to any asyncio-based application that needs to issue non-blocking HTTP calls. The same is true for WebSockets. Since they are part of the HTTP specification, you can connect to WebSocket servers and easily exchange messages with them.
When it comes to servers, aiohttp gives you everything you can expect from a microframework. The features available out-of-the-box include routing, middleware, and signals. It may seem like it’s very little, but it will suffice for a web server.
“What about the remaining functionalities?” you may ask.
As far as those are concerned, you can build the rest of the functionalities using one or many asyncio-compatible libraries. You will find plenty of them using sources like this one.
Aiohttp is built with testing in mind. Developers who want to test an aiohttp-based application will find it extremely easy, especially with the aid of pytest.
Even though aiohttp offers satisfactory performance by default, there are a few low-hanging fruits you can pick. For example, you can install additional libraries: cchardet and aiodns. Aiohttp will detect them automatically. You can also utilize the same uvloop that powers Sanic.
Last but not least: one definite advantage of aiohttp is that it is being actively maintained and developed. Choosing aiohttp when you build your next application will certainly be a good call.
There are many more Python web frameworks out there you might find interesting and useful. Each of them focuses on a different issue, was built for distinct tasks, or has a particular history.
The first that comes to mind is Zope2, one of the oldest frameworks, still used mainly as part of the Plone CMS. Zope3 (later renamed BlueBream) was created as Zope2’s successor. The framework was supposed to allow for easier creation of large applications but hasn’t won too much popularity, mainly because of the need to master fairly complex concepts (e.g. Zope Component Architecture) very early in the learning process.
Also noteworthy is the Google App Engine, which allows you to run applications written in Python, among others. This platform lets you create applications in any framework compatible with WSGI. The SDK for the App Engine includes a simple framework called webapp2, and this exact approach is often used in web applications adapted to this environment.
Another interesting example is Tornado, developed by FriendFeed and made available by Facebook. This framework includes libraries supporting asynchronicity, so you can build applications that support multiple simultaneous connections (like long polling or WebSocket).
Other libraries similar to Tornado include Pulsar (async) and Gevent (greenlet). These libraries allow you to build any network applications (multiplayer games and chat rooms, for example). They also perform well at handling HTTP requests.
Developing applications using these frameworks and libraries is more difficult and requires you to explore some harder-to-grasp concepts. We recommend getting to them later on, as you venture deeper into the wonderful world of Python.
Stack Overflow, a leading Q&A site for the global developer community, runs an annual Developer Survey that asks its 90,000-strong pool of followers comprehensive questions about their professional lives.
The survey is interesting for many reasons, not least its statistics highlighting the increasing popularity of Python among developers worldwide.
In one of the questions, developers were asked to rate their most loved web frameworks in various programming languages. Python frameworks—including Django and Flask—ranked quite high in the top 10!
We still haven’t answered one key question: which of these frameworks is the easiest for beginners to learn? Well, in terms of ease of use, smaller frameworks like web2py, Bottle, or Flask would be the best choice. The problem is that usually later on you’ll have to build more of the supporting components by yourself.
So the framework that’s the easiest to set up and use might not be the best for the particular task you have in mind. Depending on what you’re coding, the answer will determine which framework is best for your task.
On top of that, if you’re new to Python, non-technical things like community size and available resources should probably factor into your decision as well.
Which Python web framework has the best performance? The one you can finish the project with.
It is unlikely that a rapid response to a very large number of concurrent requests is essential to your success. It is, however, certain that your success depends on developing your project to the point where users can interact with the product. In that case, we would recommend Django.
Thank you for reading our article on the best Python frameworks in 2022. We hope this summary will help you decide which framework will help you the most and get you started right away.
Python offers an extensive selection of web frameworks, all of which have their strengths and weaknesses. At STX Next, we use whatever framework fits a project best, even learning new ones on the go if needed.
STX Next has grown to become one of the largest Python software agencies in the world with over 150 Python developers on board and over 18 years of experience under our belt. We’re constantly looking for enthusiastic, talented developers who live and breathe Python. If you’re interested in starting your journey with us, check out our current job opportunities.
If you enjoyed this article and would like to learn more, we have a lot of free resources on Python you may also find interesting, such as:
Should you have any more questions, not only Python-related, don’t hesitate to contact us directly—we’d be happy to help out!