https://note.com/navitime_tech/n/nc0381517d067
I shared.
NAVITIME_Tech
August 28, 2020
Hi, I'm Kenny. I'm in charge of developing services using public transportation timetables and improving the release flow at NAVITIME Japan.
This time, I'd like to talk about how we introduced FastAPI as a Python web framework.
Table of contents
A Python web framework
A web framework later than Django and Flask
Installing FastAPI
Defining the Routing
Starting the Server
Documentation
Request Parameters
Validation with Pydantic
Summary
Web frameworks in Python
There are two major web frameworks in Python
Django: a full-stack framework
Flask: a micro-framework.
It is said that Django is for large scale development and Flask is for small to medium scale development, but since the server we developed this time was a small server, we used Flask before.
However, even if you use either framework, you will need to use plugins or third party help to use the following functions.
OpenAPI
JSON Schema
GraphQL
WebSocket
Validation using type hints
Asynchronous processing
CORS configuration
Support for working with reverse proxies
Both Django and Flask lack native support for recently introduced server-side technologies and new Python 3 features.
We have been using plugins and third party libraries to compensate for these features, but when they stop working due to destructive changes caused by version upgrades, it took us quite a while to investigate which library was the cause.
This experience makes me want a modern framework.
Web frameworks later than Django and Flask
New Python web frameworks come out every year, and all of them are similar to Flask in design.
When considering the introduction of a new framework, I did some research on the following points.
It should be as simple as Flask.
It satisfies the aforementioned functional requirements.
It has a lot of GitHub stars.
Rich documentation
I checked the number of GitHub stars for Python web frameworks and found the following (as of August 25, 2020). 1.
1. flask: 51,800
2. django: 51,500
3. fastapi: 20,100
4. tornado: 19,400
Django REST Framework: 18,600
Of these, I focused on FastAPI, which came in third.
tiangolo/fastapi
FastAPI framework, high performance, easy to learn, fast to c
github.com
FastAPI is a framework that appeared in the second half of 2018, and is the most recent of the above frameworks. Nonetheless, it has this number of stars, so it's getting a lot of attention.
The biggest difference between FastAPI and other frameworks is not the difference in functionality, but rather the richness of the documentation and the intuitive design.
Even if it provides the same functionality, it is not always easy for developers to immediately understand how to use it. However, I feel that FastAPI is very low cost in the time it takes to achieve what I want to do. I think that the generous support of the Developer Experience has led to its popularity.
For these reasons, I decided to rewrite the server implemented in Flask with FastAPI.
Installing FastAPI
To install FastAPI, do the following
$ pip install fastapi uvicorn
Uvicorn is one of the implementations of ASGI, the spiritual successor of WSGI (Web Server to Web Framework Interface) used in Python server development.
When you develop servers with Flask, you will probably use Gunicorn as a WSGI server, but you can think of Uvicorn as an asynchronous version of Gunicorn.
Let's see how to use FastAPI in comparison with Flask, and install the following so that you can use both Flask and Gunicorn.
$ pip install flask gunicorn
Defining Routing
If we rewrite the routing definition written in Flask in FastAPI, it will look like this
Flask
from flask import Flask
app = Flask(__name__)
@app.route("/hello")
def hello():
return {"Hello": "World!"}
FastAPI
from fastapi import FastAPI
app = FastAPI()
@app.get("/hello")
def hello():
return {"Hello": "World!"}
The implementation is quite similar, and the transition to FastAPI was quite easy because of the similarity in the way Flask is written.
Starting the Server
Save the source codes of Flask and FastAPI as flask_app.py and fastapi_app.py, respectively. To start the server, follow the instructions below.
Flask
$ gunicorn flask_app:app
[2020-08-26 15:21:09 +0900] [27823] [INFO] Starting gunicorn 20.0.4
[2020-08-26 15:21:09 +0900] [27823] [INFO] Listening at: http://127.0.0.1:8000 (27823)
[2020-08-26 15:21:09 +0900] [27823] [INFO] Using worker: sync
[2020-08-26 15:21:09 +0900] [27826] [INFO] Booting worker with pid: 27826
FastAPI
$ uvicorn fastapi_app:app
INFO: Started server process [14366].
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
The startup method is very similar. By the way, FastAPI can also be connected to WSGI, so you can start it with Gunicorn.
Documentation
This is where FastAPI really comes into its own, as it can automatically generate documentation in both Swagger UI and ReDoc styles.
After starting the FastAPI server, you can access the following URLs to see the beautiful documentation pages.
Swagger UI: http://localhost:8000/docs
Enlarge image 1
ReDoc: http://localhost:8000/redoc
Enlarge image 2
Flask does not have a feature to automatically generate documentation. To be honest, I think it's worth installing FastAPI just to use this feature.
Request Parameters
I'm sure there are many people who have trouble understanding how to get the request parameters when using Flask. I am one of them.
Let's say you have an API like the following
POST /users/{name}?age={age}
{
"country": {country}
}
Each parameter is specified in a different part of the request.
{name} : path parameter
{age} : Query parameter
{country} : Body
FastAPI is a very intuitive way to solve this problem.
Let's take a look at how to write it (error checking is omitted).
Flask
from flask import Flask, request
app = Flask(__name__)
@app.route("/users/<name>", methods=["POST"])
def create_user(name):
age = request.args.get("age", type=int)
body = request.json
return {
"age": age,
"name": name,
"country": body["country"],
}
FastAPI
from fastapi import FastAPI, Query, Body
app = FastAPI()
@app.post("/users/{name}")
def create_user(name: str, age: int = Query(None), body: dict = Body(None)):
return {
"age": age,
"name": name,
"country": body["country"],
}
In the case of FastAPI, the path parameter, query parameter, and body can all be defined as function arguments.
Also, FastAPI is more intuitive and easier to understand because it uses the type hints introduced in Python 3 to specify the parameter types.
I remember spending a lot of time trying to figure out how to receive query parameters and bodies in Flask. It seems to me that the Developer Experience is greatly affected by the design that makes it easy to find the way to implement these commonly used functions.
Validation with Pydantic
FastAPI ships with a type validation library called Pydantic, which can be used to validate the types of request and response parameters.
Let's try to validate the response to the aforementioned API. The same method can be used to validate the request.
First of all, we need to import the following
from pydantic import BaseModel, Field
Next, define the schema class to validate the JSON returned in the response.
class User(BaseModel):
age: int = Field(description="age", ge=0)
name: str = Field(description="Name")
country: str = Field(description="Country of origin")
By using this class, you can validate that the response JSON has "age", "name", and "country" fields, and that "age" is an integer greater than or equal to 0.
We will specify this class with a decorator
@app.post("/users/{name}", response_model=User)
In this way, an error will be returned if you try to return a response that does not match the User schema.
The entire source code looks like this
from fastapi import FastAPI, Query, Body
from pydantic import BaseModel, Field
app = FastAPI()
class User(BaseModel):
age: int = Field(description="age", ge=0)
name: str = Field(description="Name")
country: str = Field(description="Country of origin")
@app.post("/users/{name}", response_model=User)
def create_user(name: str, age: int = Query(None), body: dict = Body(None)):
return {
"age": age,
"name": name,
"country": body["country"],
}
The schema description will be automatically reflected in the documentation as well.
Enlarge screenshot 2020-08-26 17.17.27
Summary
Flask is said to be a micro-framework, but FastAPI has a well-balanced design that seems to redefine the micro-framework to meet recent needs.
There are many more attractive features of FastAPI. If you want to know more about other features, please check out the official documentation.
FastAPI Documentation
#python
#NaviTime Japan
#web framework
Conskie@Conskie
NAVITIME_Tech
Follow us
Follow us on Twitter and Facebook to get the latest news about NAVITIME technology and our service. If you have any questions or comments, please visit our official website (https://www.navitime.co.jp/).
0 コメント:
コメントを投稿