Creating a Web Application and an API in Python using FastAPI: Part 1 - Introduction and Setup
I’ve always used either Python or JavaScript for writing web apps and APIs. Both these languages have a wide variety of different web and API frameworks. Express is always my choice for JavaScript whereas Flask has always been my choice when it comes to Python. I prefer Flask over Django due to its lightweight architecture and less boilerplate requirement. It’s quick and gets the job done. Also, I use Flask-RESTful paired with Flask to write APIs. Flask-RESTful simplifies many things which I had to do manually if I were to only use Flask.
But recently I got the opportunity to try out a brand-new framework called FastAPI. It’s a new Python web framework and in many ways it’s remarkably like Flask. In fact, it feels exactly like Flask but more superior due to its heavy use of many modern Python features like asyncio and type hints etc. FastAPI is built on top of Starlette and brings a ton of awesome features and high performance to the table.
Why FastAPI over others?
- Exceedingly high performance: On par with NodeJS.
- Fast to code: Develop new features up to 2-3 times faster (compared to Django and Flask). Due to FastAPI’s use of Pydantic models and type hints, a lot of the work around things like validation, data exchange and documentation is all largely automatic, so you don’t have to spend time writing all that code.
- Fewer bugs: Reduce about 40% of developer induced errors. Since you aren’t writing a lot of validation and data exchange code and most of your data, arguments are all strongly typed, you end up with far fewer bugs.
- Great editor support: Due to type hints, you’ll get autocompletion everywhere. Your editor will already know what kind of function it is, what kind of data you need to pass and will give you a whole bunch of correct suggestions. You’ll have to spend time looking at documentation and even less time debugging when errors occur.
- Easy to learn and use: If you’ve already used Flask then FastAPI will feel familiar.
- Short: We use type hints to tell Python exactly what type of data our functions and endpoint accept. Due to this, the framework does a lot of work for us. Things like ensuring a particular argument is already present, doing automatic type conversions and so on.
- Production-ready code: FastAPI comes with a production ready web server (Uvicorn) built on async and await, so you get the highest performance production grade servers that you drop right into production.
- Standards-based: One of the challenges with building HTTP based API’s is that there’s zero documentation. You must write documentation for each of your endpoints yourself or rely on regularly reading the source code. But with FastAPI, you can generate automatic documentation with Swagger (OpenAPI) to generate documentation for all your API methods.
What exactly is “Modern Python”?
FastAPI uses a lot of the newer, more recent features of Python (3.6+). Some of them are:
-
Type hints: Using type hints, you can state exactly what “type” (str, int, list etc.) of value a variable can store, or what “type” of value a function should accept and return. They also help text editors provide rich auto-completion and display bugs while writing the code, instead of facing it at runtime.
-
async / await: AsyncIO enables you to write asynchronous code. For example, instead of waiting for an HTTP request to finish before executing code further, using Python’s async coroutines you can submit the request and continue further code execution while still waiting for the HTTP request to finish. When it completes, you can do something with the response, but that won’t block or affect your current tasks waiting in the queue.
-
ASGI: ASGI servers automatically know how to run async programs correctly. They give you great scalability anytime you’re waiting on an external system; be that the database, another external web request, a cache etc.
-
Data classes: These are ways to describe how your data is supposed to be exchanged in terms of classes. FastAPI takes this further with Pydantic, so you can do that exchange and conversion automatically, so you don’t have to write all those functions manually.
Building a weather application
We will build a simple weather application that will serve an HTML page with a form asking the user to select a city, state, and country.
Our web application will get some data from the user; then make a request to OpenWeatherMap with that data, get back some response data, change it, and then return it to the user. You could do a lot more with that data such as saving it to a database, do some logging, etc. but the focus on this part of the article is to consume an external API and serve that data to the user, so we can use the powerful async/await features of FastAPI to make our API highly scalable.
Getting the weather data
We will get our weather data from OpenWeather (https://openweathermap.org/api).
To create an account, log on to https://home.openweathermap.org/users/sign_up and fill the signup form. After signup, make sure you confirm your email by visiting your email and clicking on the “Verify your email” button in the confirmation email sent by OpenWeather Team with the subject “OpenWeatherMap Account confirmation”.
Setting up our project
Almost every Python project will depend on some external libraries and anytime you have a Python application that depends on external libraries or packages, it is a good idea to create a virtual environment. That way, we don’t have any conflict with the Python packages installed globally on your system. We will create our project using the command line. I’m using Windows 10, so all my commands are Windows-specific, but the commands are more or less the same for Linux and Mac systems. I’ve provided the equivalent commands for other systems; you can use them accordingly.
I’m using Windows Terminal which is an awesome terminal application on Windows to access the command line. This is not preinstalled on every Windows machine, so you will have to download and install it yourself. You can view the installation instructions here. If you don’t want to use Windows Terminal, you can also use PowerShell which is preinstalled in and will work simply fine. On Linux and Max, you can use the built-in Terminal application.
Creating a virtual environment
Start by navigating to the Desktop and creating a new folder named python_weather_app
. After creating it go inside the new folder.
PS> cd Desktop
PS> mkdir python_weather_app
PS> cd python_weather_app
We will use Python's built-in venv module to create our virtual environment. Use the following command:
PS> python -m venv env
In the above command, env will be the name of the virtual environment. This command will create a folder with the same name. Now, to use our virtual environment, we need to activate it. Use the following command to activate it.
PS> env/scripts/activate
Once activated, you should now see the word env in your prompt.
Post-installation, there is a 95% chance that pip (Python’s package manager) will be out of date. So, let’s update that as well.
PS> python -m pip install --upgrade pip
On running this command, you will see a whole bunch of output appear. The ending line should be something like “Successfully installed pip-21.1.1”.
Opening the project in VS Code
My editor of choice is Microsoft Visual Studio Code (VS Code for short). It’s free, works on all major operating systems and has great support for Python and its ecosystem. VS Code also has a vast library of extensions that will help you with various tasks like linting (syntax checking), debugging and refactoring etc. You can download VS Code from here. If you prefer some other text editor, you can use that as far as you know your way around it. Since I am using VS Code, my instructions will be specific to it.
To open our project in VS Code, use the command below.
PS> code .
The dot indicates the current folder. So, we are telling VS Code, to open the entire folder in it.
Installing dependencies
To start building our FastAPI project, we will first need to install the fastapi package. We can do that in one of many ways. We could just type python -m pip install fastapi in the command line and install it in our virtual environment. But we will eventually need to install several other packages, and if we deploy the project to a server, we will have to install them again over there. We will have to remember all the packages we need, so we can manually run the install command for each package. This gets very tedious.
What I like to do is to keep a requirements.txt file and add the names of each package we want to install in this file. Then we can just use one command and Python will automatically install all the packages listed in the file. When we want to install another package, just add it to the file, run the same command and it will be done.
Let’s start by creating our requirements.txt file. On VS Code you can click on the little “New File” icon in your left sidebar and type in the name requirements.txt. Make sure you don’t end up creating the file inside the env folder. It should be outside, on the same level as the env folder.
Type “fastapi” on the first line in the new file. Now, run the following command to install the packages listed in the requirements.txt file. Whenever you add a new package to this file, don’t forget to run this command.
PS> pip install -r requirements.txt
After running the command, you should see some output similar to this:
Collecting fastapi
Using cached fastapi-0.63.0-py3-none-any.whl (50 kB)
Collecting pydantic<2.0.0,>=1.0.0
Using cached pydantic-1.8.1-cp39-cp39-win_amd64.whl (1.9 MB)
Collecting starlette==0.13.6
Using cached starlette-0.13.6-py3-none-any.whl (59 kB)
Collecting typing-extensions>=3.7.4.3
Downloading typing_extensions-3.10.0.0-py3-none-any.whl (26 kB)
Installing collected packages: typing-extensions, starlette, pydantic, fastapi
Successfully installed fastapi-0.63.0 pydantic-1.8.1 starlette-0.13.6 typing-extensions-3.10.0.0
We will need a few more packages to build our web app. Let’s all these to our requirements file and install them. Add the following lines to the requirement.txt file:
uvicorn
httpx
pydantic
Now run the install command once again.
PS> pip install -r requirements.txt
This concludes our basic setup. In the next article, we will start building the structure of our project and create our endpoints.