Best framework to build an API in Python

Denis Rasulev
14 min readMar 27, 2023

Python has become a popular choice for building APIs, and there are several frameworks available that can help developers create efficient, scalable and secure APIs. In this article, we’ll explore some of the best Python frameworks for API development.

Always actual version you will find on Den’s Hub

This is the second article in a series devoted to the topic of APIs.

Each article covers a different topic. If you’re just starting to understand how to write your own API, it’s useful to read everything in order. If you already know it and are interested in a particular topic, go straight to it.

  1. Simple Explanation of API
  2. Best Framework for API (this article 👇)
  3. Build API with FastAPI (soon)
  4. Build API with ChatGPT (soon)
  5. Top Tools to Test API (soon)
  6. Make Money on API (soon)

Let’s go…

API frameworks

In the previous article we figured out what an API is and how it works, so now let’s see how to choose the best framework for APIs in Python. To pick a tool that will allow you to write APIs in Python quickly and efficiently, you need to consider the following things:

  • Project size. If your API will be part of a full-fledged web application, it’s best to choose a framework that allows you to create both the web application itself and its API part. If all you need is the API, any of the micro frameworks will do.
  • Workload. This is usually directly determined by the CPU and memory requirements of the server. The most obvious parameter is the number of client-server requests the server can handle.
  • Time to assimilate. As a rule, the more powerful a framework is, the more time is required to learn it. If you already have a good command of a tool, of course, you can disregard this parameter.

A special case is a simple one, when all you need is a client to retrieve data from an existing API. To create it you can use embedded module or any of the popular libraries, like httplib2 or everyone’s favorite requests. Although it’s not directly related to the topic, we’ll take a look at them to complete the picture.

Let’s now look at the best REST API frameworks in Python that are actively supported and developed, as well as popular with developers and widely used nowadays. For your convenience, I’ve divided them into three conditional categories:

  • Client libraries
  • Micro frameworks (minimal set of features)
  • Full-stack frameworks (full set of functions)

Let’s start with a simple one…

Client libraries

Requests

Site: https://github.com/psf/requests
Type: Client Library

Requests is a very popular HTTP client library in Python. Even the official Python documentation recommends it. As its name implies, it is used to make requests to the API. The library supports all HTTP methods and advanced features such as authentication, session cookies, working with SSL and many others.

Working with Requests is very easy. Here’s an example of a Python API call when you use the GET method to authorize on a site:

>>> import requests
>>> URL = 'https://httpbin.org/basic-auth/user/pass'
>>> r = requests.get(URL, auth=('user', 'pass'))
>>> r.status_code
200
>>> r.headers['content-type']
'application/json; charset=utf8'
>>> r.encoding
'utf-8'
>>> r.text
'{"authenticated": true, ...'
>>> r.json()
{'authenticated': True, ...}

Here you will find detailed documentation on Requests library.

Faster Than Requests

Site: https://github.com/juancarlospaco/faster-than-requests/
Type: Client Library

Quite an interesting package, which is actively developing. According to the developer it works faster than Requests :) Perhaps this is because it mainly uses the Nim language. There is a performance comparison on the main repository GitHub page. It is also claimed that the library is much more compact in terms of number of lines of code.

The most handy thing about this library is the many helper functions that go beyond the usual HTTP methods. It has several handy functions for tasks such as finding URLs, downloading resources such as image files, or merging requests to multiple URLs and returning a single response.

Here are some examples of standard Python API requests:

import faster_than_requests as requests

# GET
requests.get("http://httpbin.org/get")

# POST
requests.post("http://httpbin.org/post", "Some Data Here")

# Download a file
requests.download("http://example.com/foo.jpg", "out.jpg")

# Multi-Threaded Web Scraper
requests.scraper(["http://foo.io", "http://bar.io"], threads=True)

# URL-to-SQLite Web Scraper
requests.scraper5("http://foo.io", sqlite_file_path="database.db")

# Regex-powered Web Scraper
requests.scraper6("http://python.org", "(www|http:|https:)+[^s]+[w]")

# CSS Selector Web Scraper
requests.scraper7("http://python.org", "body > div.someclass a#someid")

# WebSockets Binary/Text
requests.websocket_send("ws://echo.websocket.org", "data here")

PycURL

Site: http://pycurl.io/
Type: Client Library

PycURL is just a Python add-on for the libcurl library, which is used to transfer files over various protocols. It supports HTTP, FTP, SMTP and many others. If you like cURL or libcurl libraries, you might also like this Python interface for the native libcurl library, written in C/C++.

You’ll find a lot of interesting stuff in the official repository PycURL on GitHub. For more details about the library, also read the official documentation.

Below is an example of how to make an HTTP GET call with PycURL.

import pycurl
from io import BytesIO

buffer = BytesIO()
c = pycurl.Curl()
c.setopt(c.URL, 'http://pycurl.io/')
c.setopt(c.WRITEDATA, buffer)
c.perform()
c.close()

body = buffer.getvalue()
# Body is a byte string.
# You need to know the encoding in order to output it to a text file,
# for example, in standard output.
print(body.decode('iso-8859-1'))

urllib3

Site: https://urllib3.readthedocs.io/
Type: Client Library

This Python library has a special class for managing connection pools with support for multithreading, file uploads, forms, exception handling, and more. It has a friendly interface, good documentation, and even built-in support for third-party libraries.

urllib3 is a powerful and easy to use HTTP client for Python. The functionality of the library allows to organize fast and reliable work with almost any source of information on the Internet.

Most of the Python ecosystem is already using urllib3, so you might want to take a closer look at this library as well.

Examples of Python API calls in the urllib3 library:

>>> import urllib3
>>> http = urllib3.PoolManager(num_pools=2)
>>> resp = http.request('GET', 'http://yahoo.com/')
>>> resp = http.request('GET', 'http://google.com/')
>>> resp = http.request('GET', 'http://httpbin.org/robots.txt')
>>> resp.status
200
>>> resp.data
b"User-agent: *\nDisallow: /deny\n"

Micro frameworks

Flask

Site: https://flask.palletsprojects.com/
Type: Micro framework

The project started as a simple wrapper around Werkzeug and Jinja, and today has become one of the most popular frameworks for Python web application development, including API creation. The project repository on GitHub already has over 60,000 stars. Flask makes it easy to get started, gets your first results quickly, and gradually scales your application to any level.

Over the years, Flask has added many features that put it almost on par with full stack frameworks. However, it is its minimalistic approach to building web applications that makes it the preferred choice for many developers.

Flask offers a variety of options for achieving your goal and does not force you to use specific libraries or follow a strictly defined project structure. You can choose the tools and libraries you want to use yourself.

The flip side of flexibility

There are many useful extensions developed and supported by the community, which makes it easy to add functionality to your application.

This is how you can write a simple “Hello World” web application in Flask:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello_world():
return 'Hello, World!'

if __name__ == '__main__':
app.run()

You’ll find more information and documentation about Flask on the project website, and a list of additional resources and plugins in this repository on GitHub.

I also recommend the official tutorial by Miguel Grinberg himself, the excellent article series on Hackers and Slackers, and the user community on Reddit.

Tornado

Site: https://www.tornadoweb.org/
Type: Micro framework

Tornado is a framework and asynchronous networking library. It also includes an HTTP server and client interface, as well as a WebSocket interface for two-way communication with servers that support WebSocket.

Tornado supports all the basic middleware features needed to handle HTTP requests and responses, templates, and routing.

It also supports coroutines (cooperative routes), making it a great tool for creating server backends with long data retrieval cycles and persistent connections, especially for WebSockets.

What are coroutines

A simple backend for the API in Tornado can be done as follows:

import asyncio
import tornado.web

class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])
async def main():
app = make_app()
app.listen(8888)
await asyncio.Event().wait()
if __name__ == "__main__":
asyncio.run(main())

Tornado has been around for a long time, but some of its features are a bit outdated compared to modern REST frameworks. Nevertheless, it is very popular, as repository on GitHub has almost 21 thousand stars.

FastAPI

Site: https://fastapi.tiangolo.com/
Type: Micro framework

FastAPI is one of the newer Python frameworks. According to the developers, it is very fast, high-performance, and supports a compact coding structure, which leads to very fast application development.

FastAPI is based on the asyncio capabilities in Python, which have been standardized as an ASGI specification for creating asynchronous web applications. FastAPI is almost as powerful as Flask and supports built-in procedures for integrating with databases, performing background tasks, connecting custom middleware, and more.

With over 50,000 stars at repository on GitHub, FastAPI is gaining popularity in the Python community and is constantly being developed by a group of active professionals of over 100 people.

Here’s how you can create a simple REST API using FastAPI:

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
return {"Hello": "World"}

@app.get("/items/{item_id}")
def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}

Official documentation: https://fastapi.tiangolo.com
GitHub repository: https://github.com/tiangolo/fastapi

Sanic

Site: https://sanic.dev/en/
Type: Micro framework

Sanic is another asyncio-based Python web framework. It is a very lightweight framework with support for all basic HTTP and middleware application functions.

In addition, Sanic supports the ability to write custom protocols and middleware components to customize the request and response protocol. Sanic has its own built-in web server to speed up development, and also integrates well with Nginx for industrial applications.

Here’s how to write a simple API in Sanic:

from sanic import Sanic
from sanic.response import json

app = Sanic()

@app.route('/')
async def test(request):
return json({'hello': 'world'})

if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000)

For more information, see Sanic repository on GitHub or Sanic Getting Started Guide.

Falcon

Site: https://falconframework.org/
Type: Micro framework

Falcon is a simple and robust framework for building large-scale application backends and microservices. It supports the REST architectural style and works with WSGI or ASGI compatible servers.

Falcon has an object-oriented, class-based interface for defining API resources. It supports basic HTTP and middleware application functions, including HTTP protocol processing, routing, media handling, cookies, and URI utilities.

Here’s how to create a REST API using Falcon’s object-oriented approach:

class QuoteResource:
def on_get(self, req, resp):
"""Handles GET requests"""
quote = {
'quote': (
"I've always been more interested in "
"the future than in the past."
),
'author': 'Grace Hopper'
}
resp.media = quote

api = falcon.API()
api.add_route('/quote', QuoteResource())

More information can be found in the Falcon repository on GitHub. To start developing on Falcon, it is recommended to read the official documentation of the project.

Bottle

Site: https://bottlepy.org/
Type: Micro framework

Bottle is a very lightweight micro framework. It is very small in size, distributed as just one file, and depends only on the standard Python library.

Bottle is great for:

  • Rapidly prototyping ideas
  • Learning how frameworks are built
  • Creating and running simple personal web applications

At the same time, Bottle provides all the components you need to create a complete backend for a REST API that relies on routing and templates. It supports most of the usual HTTP-related functions such as cookies, headers, metadata, and file uploads. It also has a built-in HTTP server.

A quick and simple application on Bottle looks like this:

from bottle import route, run, template

@route('/hello/<name>')
def index(name):
return template('<b>Hello {{name}}</b>!', name=name)

run(host='localhost', port=8080)

For more information, see repository Bottle on GitHub. In official documentation you will find a quick-start guide, configuration details and a collection of useful articles.

Hug

Site: https://www.hug.rest/
Type: Micro framework

hug is really a multi-interface API framework. It offers a great way to create REST APIs by separating the business logic of the API from the interface itself, and by associating version dependencies.

Because hug is focused on API creation, its capabilities are strictly limited to I/O processing, routing, and type annotations. It does, however, support the ability to add extensions.

One of the interesting features of hug is the ability to provide API logic via CLI, HTTP, or a local function, allowing you to use hug as a standard Python module.

Here’s how to write an API in hug:

import hug

@hug.get('/happy_birthday')
def happy_birthday(name, age:hug.types.number=1):
"""Says happy birthday to a user"""
return "Happy {age} Birthday {name}!".format(**locals())

👉 Note that when using hug there may be a problem if you need to pre-process the requests you receive. Since the request body is passed to the thread, you can only read it once.

Therefore, if you read the request body in a method that pre-processes requests, the thread will remain empty and hug won’t be able to get input parameters from it. The problem is solved by creating an additional thread before reading the parameters.

You will find more information in hug repository on GitHub, as well as in hug official documentation.

Eve

Site: https://python-eve.org/
Type: Micro framework

Eve is a micro framework for APIs built on top of Flask. Eve’s goal is to make REST API development extremely fast and easy. That’s why it’s built on Flask principles, leaving aside all the Flask web application components.

Eve supports all the most used REST API templates, such as CRUD operations, customizable API endpoints, filtering, sorting, multi-page, JSON/XML/JSONP formats.

It also supports advanced features such as authentication, CORS, caching, rate limiting and more. Eve also supports integration with MongoDB and SQL databases.

Eve can use configuration file in Python format to define resources and API endpoints. Thus, the REST API can be built using declarative JSON syntax.

For more information, read the Getting Eve up and running guide or check out the Eve repository GitHub.

Full stack frameworks

Django

Site: https://www.djangoproject.com/
Type: Full stack framework

Django is a full-featured, full-stack Python web framework. It is one of the oldest and most popular web frameworks, Django repository has almost 67 thousand stars on GitHub.

Django framework has a lot of features for creating full-fledged web applications. In addition to supporting all the necessary HTTP functionality, including middleware applications, its features include MVC samples, data views, database handling, forms, templates, security, caching, and more.

Of course, using Django only to create a REST API backend is clearly overkill. That’s why you can use a special framework Django REST, which is a community-supported project, for this purpose. It uses Django as a base engine, providing a simpler interface specific to REST API development.

Check out the official Django repository and/or the official Django REST repository for more information on working with them. And at this link you’ll find the Django REST Quick Start Guide.

TurboGears

Site: https://turbogears.org/
Type: Fullstack framework

TurboGears is another full-stack framework. The main idea in its development was to allow the project to scale from a simple application (in a single file) to a full stack application. In this way, TurboGears can give the feeling of working with a micro frame, but it also provides all the tools you need to develop a full-fledged web application.

TurboGears is built with the MVC (Model-View-Controller) schema like other full-featured frameworks. It supports templates, page management, authentication and authorization, caching, and support for various databases and schema migration.

The most basic version is created very simply. Make a file tgapp.py and declare a controller in it:

class RootController(TGController):
@expose()
def index(self):
return 'Hello World'

@expose()
def hello(self, person):
return 'Hello %s' % person

For the controller to work, you need to create an application:

from tg import MinimalApplicationConfigurator

config = MinimalApplicationConfigurator()
config.update_blueprint({'root_controller': RootController()})

application = config.make_wsgi_app()

Finally, give the command to run this application:

from wsgiref.simple_server import make_server

print("Serving on port 8080...")
httpd = make_server('', 8080, application)
httpd.serve_forever()

Then run the application with the command python tgapp.py and it will start the server on port 8080. Open your browser, type in the address http://localhost:8080 and you will see your text Hello, world.

And if you send the query http://localhost:8080/hello?person=MyName, you’ll see the response Hello MyName.

That’s it.

Check out the TurboGears repository on GitHub to get a better understanding of the framework. And to get started, study the TurgoGears documentation.

web2py

Site: http://www.web2py.com/
Type: Fullstack framework

Web2py is an open-source, full-stack framework written and programmed in Python. Its main goal is to develop fast, scalable, and secure database-driven web applications.

At the core of web2py are modules for handling HTTP and URLs. It also has a built-in scheduler for performing background tasks. In addition, web2py has a database abstraction layer that maps Python objects to database objects such as tables, queries, and records.

The database abstraction layer works in conjunction with a set of drivers that support many popular databases, such as SQLite, MySQL, PostgreSQL, Oracle, DB2, MSSQL, MongoDB, and others.

It also has full-featured support for MVC, form validation, security, access control, and many other utilities.

web2py comes in binary packages that you run on your computer and then, through the web interface, create your web application or service.

For a detailed look at web2py repository on GitHub. The project also has excellent documentation in various languages, both official and community-generated, with examples and tutorial videos.

Pyramid

Site: https://trypyramid.com/
Type: Fullstack framework

Pyramid is another full-featured Python web framework whose basic idea is to start small and grow to a large project as needed. This approach allows developers to start with Pyramid as a micro-framework.

In addition, Pyramid is flexible enough to expand and add new components to handle all the tasks needed to build a large-scale web application.

Pyramid includes all the standard web framework features such as MVC schema, routing, templates, security, sessions, databases, and logging. It also has a built-in web server called pserve, but works seamlessly with Apache and Nginx for serious applications.

Here is an example of a simple backend on Pyramid.

from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response

def hello_world(request):
return Response('Hello World!')

if __name__ == '__main__':
with Configurator() as config:
config.add_route('hello', '/')
config.add_view(hello_world, route_name='hello')
app = config.make_wsgi_app()
server = make_server('0.0.0.0', 6543, app)
server.serve_forever()

As in previous cases, I recommend reading the Pyramid repository on GitHub, the Pyramid Quick Start Guide, and the official Pyramid documentation.

Conclusion

The article is quite long and you have to understand that it’s just a brief overview of some of the most popular solutions for developing your API. You can always look at more detailed information and choose the product you like best to create your own unique project.

And I’ll share another link that’s good to check out. It’s a performance comparison of many frameworks for web applications that do fundamental tasks like JSON serialization, database access, and server-side template processing.

Each framework runs in a realistic configuration. Results are obtained on cloud instances and on physical hardware. Test implementations were mostly created by the community, and all source code is available at repository GitHub.

In the next part, we’ll look at a practical example of how to write your API and then properly document it.

Good luck! 👍

©2019–2023 Denis Rasulev · CC BY-NC-ND 4.0 · Den’s Hub

--

--

Denis Rasulev

B2B Sales & Channels Growth Expert · Digital Marketing Pro · Tech & IT Sector · Consulting Services