Abandoning Flask for FastAPI
All across Medium and social media, my feeds have constantly been posts about why people should use FastAPI for writing APIs in Python. Seeing this, I was a little shocked, because I was under the impression that Flask and Django were the major Python API frameworks. For the last few years, Flask has been my go-to framework for writing APIs. With all this hype surrounding FastAPI, I decided to give it a try.
Giving it a Try
With the discovery of FastAPI, I decided to revisit an API that was built a few months ago to handle application logging. Essentially, the plan was to convert this logging API from Flask to FastAPI. The first step in this process is to install a couple of Python modules.
pip3 install fastapi
pip3 install uvicorn
pip3 install pydantic
After installing the modules, I refreshed my memory on the endpoints for the previous version of the logging API.
- GET request — /loggingapi/v1/logs
- POST request — /loggingapi/v1/log
The GET request is pretty straightforward. It gathers all logs for a given application ID. Right now, I am dealing with a relatively small amount of logs, so returning all records will be fine. However, in the future, this will probably get changed to date parameters to limit the number of records being returned.
The POST request is even easier than the GET request. Essentially, its purpose is to add new log records to the database. It takes an object parameter that looks similar to this:
"message": "This is my log message."}
With my memory of the endpoints refreshed, code writing could begin. The first bit I wrote was a new initialization of FastAPI with some metadata.
After that, I started writing the GET request.
Making comparisons to Flask, there are quite a few differences. Instead of having to use “methods=[“GET”]”, this has been turned into a function that contains the endpoint URL. The other major difference is that all endpoint parameters whether they are passed through the URL or passed in the body of the request must be passed to the endpoint function. The “storage” module contains the functions to query the database. Not major changes were required for the transition to FastAPI.
Since I was getting a little itchy to try out the new endpoint, I decided to start up the API in development mode. In Flask, when not using a virtual environment, it was customary to use the “python3” command when running an API. However, this will not work with FastAPI. The “uvicorn” command is an ASGI server implementation. The command I used to run the API was this:
uvicorn app:app --reload
Now that the server had the API running, I opened up Postman, entered the endpoint, an application ID, and then sent the request. Unfortunately, the formatting of the output looked a little funny. I soon discovered that FastAPI sends responses as JSON by default. Therefore, I needed to remove the “json.dumps()” in my “storage” module. Below is the output of the second attempt to send the request.
GET request test.
With the GET request looking pretty good, I wanted to check out the built-in swagger documentation. Not going to lie, I thought it was a little too good to be true, but was completely blown away when I navigated to the documentation page.
Before doing any more experimentation, I really need to finish the POST endpoint. Unlike the GET endpoint, this one takes a JSON object in the body of the request. In Flask, I was accustomed to using “request.json” to get the data. However, FastAPI uses “pydantic” to create a class object. Here is the one I created.
Like the GET endpoint, the log parameter needs to be passed through the endpoint function as type “Log”.
At this point, I was able to run the test for the POST request in Postman.
POST request test.
I think it is safe to say that I will be using the FastAPI framework for all my Python APIs. Even though I was just converting from Flask to FastAPI, I noticed a considerable amount of time savings while writing out the endpoints. I love how asynchronous tasks are integrated by default. Flask does have support for asynchronous tasks, but the “celery” module needs to be imported. Same thing when it comes to sending responses in Flask (“json” module is needed). FastAPI by default sends responses as JSON objects. Finally, the swagger documentation is amazing! To be honest, I never tried to get swagger working with Flask. Again, FastAPI supports it by default and makes it so easy to configure and update. Feel free to leave a comment about what you like/dislike about FastAPI. Until we meet again, cheers!