FastAPI 是一个用于构建 API 的现代、快速(高性能)的 web 框架,使用 Python 3.6+ 并基于标准的 Python 类型提示。
官方中文文档:https://fastapi.tiangolo.com/zh/
官方文档: https://fastapi.tiangolo.com
源码: https://github.com/tiangolo/fastapi
FastAPI依赖于下面这两大重要的成果:
fastapi安装
pip install fastapi
pip install uvicorn
可选的依赖
根据官方介绍,我们看到FastAPI的速度得益于使用了Starlette——一个轻量级的ASGI框架。
ASGI,全称为Asynchronous Server Gateway Interface,为了规范支持异步的Python Web服务器、框架和应用之间的通信而定制,同时囊括了同步和异步应用的通信规范,并且向后兼容WSGI。由于最新的HTTP协议支持异步长连接,而传统的WSGI应用支持单次同步调用,即仅在接受一个请求后返回响应,从而无法支持HTTP长轮询或WebSocket连接。在Python3.5增加async/await特性之后,基于asyncio和协程的异步应用编程变得更加方便。ASGI协议规范就是用于asyncio框架的最低限度的底层服务器/应用程序接口。
异步非阻塞I/O & 协程
阻塞I/O,非阻塞I/O,I/O多路复用都属于同步I/O。而异步I/O则不一样,当进程发起I/O操作之后,就直接返回再也不理睬了,直到kernel发送一个信号,告诉进程说I/O完成。在这整个过程中,进程完全没有被阻塞。在非阻塞I/O中,虽然进程大部分时间都不会被阻塞,但是它仍然要求进程去主动的查询,并且当数据准备完成以后,也需要进程主动的再次调用recvfrom()来将数据拷贝到用户内存。
相对于线程,协程是程序级的I/O调度,是对一个线程进行分片,使得线程在代码块之间来回切换执行,而非逐行执行,因此能够支持更快的上下文切换。协程本身并不能实现高并发,但与I/O切换结合后能够大大提高性能。每当发生I/O,自动切换协程,让出CPU资源,即可减少高并发场景下服务的响应时间。因此,结合async/await语法,将代码块定义为协程,使用异步服务器即可实现程序级I/O切换和协程调度。
快速:可与 NodeJS 和 Go 比肩的极高性能(归功于 Starlette 和 Pydantic)。最快的 Python web 框架之一。
高效编码:提高功能开发速度约 200% 至 300%。
更少 bug:减少约 40% 的人为(开发者)导致错误
智能:极佳的编辑器支持。处处皆可自动补全,减少调试时间。数据类型校验。
简单:设计的易于使用和学习,阅读文档的时间更短。
简短:使代码重复最小化。通过不同的参数声明实现丰富功能。bug 更少。
健壮:生产可用级别的代码。还有自动生成的交互式文档。
标准化:基于(并完全兼容)API 的相关开放标准:OpenAPI (以前被称为 Swagger) 和 JSON Schema。
# -*- encoding: utf-8 -*-
"""
@Author: cuiyonghua
@CreateDate: 2020/08/30 10:27 上午
@File: 第一个案例.py
@Description:
"""
from typing import Optional
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"message": "Hello World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
if __name__ == '__main__':
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8000)
将会看到如下 JSON 响应:
{"item_id": 5, "q": "somequery"}
通过 路径 / 和 /items/{item_id} 接受 HTTP 请求。
以上 路径 都接受 GET 操作(也被称为 HTTP 方法)。
/items/{item_id} 路径 有一个 路径参数 item_id 并且应该为 int 类型。
/items/{item_id} 路径 有一个可选的 str 类型的 查询参数 q。
现在访问 http://127.0.0.1:8000/docs。
你会看到自动生成的交互式 API 文档(由 Swagger UI生成):
升级版API文档可访问:http://127.0.0.1:8000/redoc
# -*- encoding: utf-8 -*-
"""
@Author: cuiyonghua
@CreateDate: 2020/08/30 10:11 上午
@File: 自定义响应状态码.py
@Description:
"""
from fastapi import FastAPI
from starlette import status
app = FastAPI()
# 201
@app.get("/201/", status_code=status.HTTP_201_CREATED)
async def item201():
return {"httpStatus": 201}
# 302
@app.get("/302/", status_code=status.HTTP_302_FOUND)
async def items302():
return {"httpStatus": 302, "message": '请求被禁止'}
# 404
@app.get("/404/", status_code=status.HTTP_404_NOT_FOUND)
async def items404():
return {"httpStatus": 404}
# 500
@app.get("/500/", status_code=status.HTTP_500_INTERNAL_SERVER_ERROR)
async def items500():
return {"httpStatus": 500}
if __name__ == '__main__':
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8000)
# -*- encoding: utf-8 -*-
"""
@Author: cuiyonghua
@CreateDate: 2020/08/30 10:01 上午
@File: 中间件_计算回调时间.py
@Description:
"""
import time
from fastapi import FastAPI
from starlette.requests import Request
app = FastAPI()
@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
start_time = time.time()
response = await call_next(request)
process_time = time.time() - start_time
response.headers["X-Process-Time"] = str(process_time)
print(response.headers)
return response
@app.get("/")
async def main():
return {"message": "Hello World"}
if __name__ == '__main__':
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8000)
总的来说,你就像声明函数的参数类型一样只声明了一次请求参数、请求体等的类型。
你使用了标准的现代 Python 类型来完成声明
你不需要去学习新的语法、了解特定库的方法或类,等等。
只需要使用标准的 Python 3.6 及更高版本。(全部都基于标准的 Python 3.6 类型声明(感谢 Pydantic )。没有新的语法需要学习。只需要标准的 Python 。)
安全性及身份验证:集成了安全性和身份认证。杜绝数据库或者数据模型的渗透风险。
OpenAPI 中定义的安全模式,包括:
所有的这些都是可复用的工具和组件,可以轻松与你的系统,数据仓库,关系型以及 NoSQL 数据库等等集成。