FastAPI
FastAPI 速度快、上手快、开发快,生产环境可用
文档: https://fastapi.tiangolo.com
源码: https://github.com/tiangolo/fastapi
FastAPI 基于 Python 3.7+ 及 Python 标准类型提示,是快速构建高性能 API 的现代 Web 框架。
核心特性:
- 速度快:归功于 Starlette 和 Pydantic,FastAPI 具有可与 NodeJS 和 Go 比肩的极高性能,是最快的 Python 网络框架之一。
- 开发快:开发速度提高约 200% 至 300%*。
- Bug 少:人为错误减少约 40%*。
- 智能:强大的编辑器支持,处处皆可自动补全,减少调试时间。
- 简单:易学、易用,阅读文档所需时间更短。
- 简短:代码重复最小化,通过不同的参数声明实现丰富功能,Bug 更少。
- 健壮:生产级别的代码,还有自动交互文档。
- 标准:完全兼容并基于 API 开放标准:OpenAPI(曾用名为 Swagger)和 JSON Schema。
* 根据对某线上应用内部开发团队的测试估算得出。
赞助商¶
评价¶
「[...] 最近我一直在用 FastAPI。[...] 实际上,我打算用 FastAPI 实现微软团队的所有机器学习服务。目前,我们正把一些服务集成至 Windows 和 Office 等核心产品。」
「我们用 FastAPI 创建获取预测结果的 REST 服务。[用于 Ludwig]」
「Netflix 很荣幸地宣布,正式开源危机管理编排框架:Dispatch![使用 FastAPI 构建]」
「FastAPI 让我欣喜若狂。它太棒了!」
「老实说,您的作品看起来非常可靠和优美。这就是我心目中的 Hug - 看到有人实现了,真的很鼓舞人心。」
「如果您想学习开发 REST API 的现代 Web 框架,看下 FastAPI 吧 [...] 它易学、易用、速度快 [...]」
「我们已经将 API 服务切换到了 FastAPI [...] 我觉得您也会喜欢 [...]」
Typer,命令行中的 FastAPI¶
如果您开发的不是 Web API,而是在终端中运行的命令行应用,不妨试下 Typer。
Typer 是 FastAPI 的小兄弟,立志要成为命令行中的 FastAPI。 ⌨️ 🚀
依赖支持¶
Python 3.7+
FastAPI 站在以下巨人的肩膀上:
安装¶
$ pip install fastapi
---> 100%
FastAPI 还需要 ASGI 服务器,生产环境下可以使用 Uvicorn 或 Hypercorn。
$ pip install uvicorn[standard]
---> 100%
示例¶
创建应用¶
- 创建
main.py
,写入以下代码:
from typing import Optional
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: Optional[str] = None):
return {"item_id": item_id, "q": q}
或者使用 async def
...
如果代码中使用了 async
/ await
,请使用 async def
:
from typing import Optional
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
笔记:
如果不清楚是否应该使用异步,请参阅文档等不及了?中对 async
和 await
的介绍。
运行¶
执行以下命令运行服务器:
$ uvicorn main:app --reload
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [28720]
INFO: Started server process [28722]
INFO: Waiting for application startup.
INFO: Application startup complete.
关于 uvicorn main:app --reload
命令......
uvicorn main:app
命令含义如下:
main
:main.py
( Python 模块)。app
:main.py
中通过app = FastAPI()
创建的对象。--reload
:代码更新后,重启服务器。仅在开发时使用。
查看文档¶
打开浏览器,访问 http://127.0.0.1:8000/items/5?q=somequery。
返回如下 JSON 响应:
{"item_id": 5, "q": "somequery"}
至此,我们就创建了具有以下功能的 API:
- 通过路径
/
和/items/{item_id}
接收 HTTP 请求。 - 这两个路径都能接收
GET
操作(也叫作 HTTP 方法)。 /items/{item_id}
路径包含类型为int
的路径参数item_id
。/items/{item_id}
路径还包含可选的,类型为str
的查询参数q
。
API 交互文档¶
访问 http://127.0.0.1:8000/docs。
查看由 Swagger UI 自动生成的 API 文档:
备用 API 文档¶
访问 http://127.0.0.1:8000/redoc。
查看由 ReDoc 自动生成的 API 文档:
更新示例¶
修改 main.py
,从 PUT
请求中接收请求体。
借助 Pydantic 使用 Python 标准类型声明请求体。
from typing import Optional
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: Optional[bool] = None
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
@app.put("/items/{item_id}")
def update_item(item_id: int, item: Item):
return {"item_name": item.name, "item_id": item_id}
(因为之前为 uvicorn
命令添加了 --reload
选项),服务器会自动重载。
更新 API 文档¶
访问 http://127.0.0.1:8000/docs。
- 自动更新 API 文档,包括新的请求体:
- 点击「Try it out」按钮,填写参数,直接调用 API:
- 然后,点击「Execute」按钮,用户界面和 API 通信,发送参数,获取结果,并在屏幕上显示:
更新备用文档¶
访问 http://127.0.0.1:8000/redoc。
- 备选文档也会显示新加入的请求参数和请求体:
小结¶
总的来说,和声明函数的参数一样,只需声明一次参数类型和请求体。
在此,使用了现代 Python 的标准类型进行声明。
开发者不用学习新语法,也不用了解特定库的方法或类。
只要使用标准的 Python 3.7+。
例如,声明 int
:
item_id: int
或使用更复杂的 Item
模型:
item: Item
......只需一次声明,就可以获得以下好处:
- 编辑器支持,包括:
- 自动补全。
- 类型检查。
- 数据校验:
- 校验失败时,自动生成清晰的错误信息。
- 对多层嵌套的 JSON 对象依然执行校验。
- 转换输入数据:转换为 Python 数据与类型。可从以下对象中读取:
- JSON
- 路径参数
- 查询参数
- Cookie
- 请求头
- 表单
- 文件
- 转换输出数据:把 Python 数据类型转换为供网络传输的( JSON )数据:
- Python 基础类型 (
str
、int
、float
、bool
、list
等) datetime
对象UUID
对象- 数据库模型
- ......及更多其他类型
- Python 基础类型 (
- 自动生成 API 交互文档,包括两种用户界面:
- Swagger UI
- ReDoc
回顾本章的代码示例,FastAPI 可以:
- 校验
GET
和PUT
请求的路径中是否含有item_id
; - 校验
GET
和PUT
请求中的item_id
是否为int
类型- 如果不是
int
类型,客户端返回错误信息
- 如果不是
- 检查
GET
请求中是否包含可选查询参数q
(比如http://127.0.0.1:8000/items/foo?q=somequery
)q
声明为= None
,所以是可选的- 没有
None
,q
就是必选的(如PUT
例子中的请求体)
- 对于访问
/items/{item_id}
的PUT
请求,把请求体读取为 JSON,并且:- 检查是否包含必选属性
name
,并且值的类型为str
- 检查是否包含必选属性
price
,并且值的类型为float
- 检查是否包含可选属性
is_offer
, 如果包含,值的类型应为bool
- 以上过程也适用于多层嵌套的 JSON 对象
- 检查是否包含必选属性
- 自动转换 JSON
- 通过 OpenAPI 文档存档所有内容,可被用于:
- API 文档
- 其他编程语言的客户端代码自动生成系统
- 直接提供两种 API 文档
虽然本篇的介绍比较浅,但涵盖了 FastAPI 的所有工作原理。
试着把下面这行代码:
return {"item_name": item.name, "item_id": item_id}
......从:
... "item_name": item.name ...
......改为:
... "item_price": item.price ...
......注意,编辑器可以自动补全属性,还能识别属性的类型:
用户指南中介绍了包含更多功能的完整示例。
剧透警告: 用户指南中的内容有:
- 声明各种来源的参数,如:请求头、cookies、form 表单及上传文件
- 设置校验约束,如
maximum_length
或regex
- 强大、但易用的依赖注入系统
- 安全和身份验证,支持 OAuth2、JWT Token、HTTP 基本身份验证等方式
- (借助 Pydantic)使用更高级,但同样简单的技术声明深度嵌套 JSON 模型
- (借助 Starlette)实现以下更多功能:
- WebSockets
- GraphQL
- 基于
requests
和pytest
的简单测试 - CORS,跨域资源共享
- Cookie Sessions
- ......以及更多
性能¶
独立机构 TechEmpower 的基准测试结果显示,基于 Uvicorn 运行的 FastAPI 是最快的 Python 网络框架之一,仅次于(FastAPI 内部使用的) Starlette 和 Uvicorn。(*)
详见基准测试一章。
可选依赖支持库¶
用于 Pydantic:
ujson
- 更快的 JSON解析email_validator
- 用于 email 校验
用于 Starlette:
requests
- 使用TestClient
时安装aiofiles
- 使用FileResponse
或StaticFiles
时安装jinja2
- 使用默认模板配置时安装python-multipart
- 通过request.form()
解析表单时安装itsdangerous
- 需要SessionMiddleware
支持时安装pyyaml
- 使用 Starlette 的SchemaGenerator
时安装(FastAPI 可能不需要此支持库)graphene
- 需要GraphQLApp
支持时安装ujson
- 使用UJSONResponse
时安装
用于 FastAPI / Starlette:
使用 pip install fastapi[all]
可安装上述所有依赖支持库。
许可协议¶
本项目遵循 MIT 许可协议。