FastAPI
介绍:高性能、自动交互式文档生成、支持类型注解、支持异步请求和RESTful API的Web框架,兼容基于ASGI的其他框架,例如Pydantic。
作用:可以用于构建前后端分离和微服务的Web应用,构建RESTful API; 接收、返回和处理JSON数据。
安装:
- FastAPI依赖Python 3.8及以上版本
- 可使用pip install “fastapi[all]” 安装FastAPI和所有可选依赖。
- 使用注意事项
- 使用时需要注意异步ASGI服务器 uvicorn 看看是否正确安装,他是支持高性能和异步编程的Web服务器,常用于开发和在生产环境运行FastAPI应用程序。
- uvicorn命令样例:uvicorn main:app –reload.在FastAPI程序编写好后,可以用这个命令启动程序。
其中uvicorn 表示启动FastAPI应用程序, - main表示需要启动的命令程序所在的Python文件位置,需要确保当前工作目录中存在这个文件,而且这个文件内容要正确。
- app表示指定文件main中需要启动的FastAPI实例对象,要确保main文件中定义了app对象。
- –reload uvicorn参数,表示uvicorn在检测源代码更改时要自动重载应用程序,有利于修改代码后立即看到结果,无需手动重启服务。
4. 启动 uvicorn命令后,可以使用ctrl + c命令退出服务器
5. from fastapi import FastAPI:FastAPI是FastAPI的核心类,依赖它构建FastAPI应用实例,定义和管理应用组件和路由。
交互式API文档
- 用途:基于OpenAPI规范的实时反应代码的最新更改,可以直接在文档中做API测试,对输入参数类型和格式能自动验证。
- 风格和命令:
- Swagger UI风格:http://127.0.0.1:端口/docs
- ReDoc 风格:http://127.0.0.1:端口/redoc
- 使用注意:
- 修改完成代码后,要等到热重载机制生效,重新触发加载,关闭旧服务器进展,启动新服务器进程后,再ctrl + r 刷新才能看到API文档的变化。
- 为防止缓存影响查看API文档,可以先清楚浏览器缓存或者使用隐私模式或者无痕模式访问。
路由、请求和响应配置
- 路由基本配置:FastAPI实例+@实例装饰器(配置路由路径和路径参数)+路由处理函数(可配置默认值的查询参数)
- 路由路径:在路径中添加{},可以创建动态路径。
- 查询参数:通过为函数参数设置默认值,可以将其作为查询参数。
- 请求体:使用pydantic库定义数据模型作为请求体结构,以包含多个默认值的字段。
- 响应模型:路由设置response_model参数,可以定义响应数据的结构。
- 路由处理函数使用:路由处理函数中返回值为字典或pydantic库的实例,字典和实例会被FastAPI自动转化为JSON格式,做为响应的结果传回客户端。
- 请求头Header和Cookie数据:使用fastapi库中的Header和Cookie类型注解,获取请求头Header和Cookie数据
- 响应头JSONResponse:使用fastapi.responses中的JSONResponse,实现自定义响应头。
- 重定向:使用fastapi.responses中的RedirectResponse,实现重定向,将新路由路径重定向到旧的路由路径中。
- 异常反馈:raise HTTPException(status_code, detail),为定位未捕获的异常导致的服务崩溃,可以在代码中添加from fastapi import HTTPException,添加异常处理来检查问题原因,返回自定义的状态码和详细信息。
- 注意:
- 可以使用typing库中的Union类型,用于支持多种数据类型的参数注解,或者用于查询参数的多种数据类型适配。例如Union[str, None]
FastAPI Pydantic
- 功能:数据验证和序列化的模型库,用于定义请求体、响应体和其他数据模型,实现类型检查和自动文档生成。
- 定义 Pydantic 模型:创建继承自 pydantic.BaseModel 的类,定义字段和数据类型,数据类型是任何有效的Python类型,字段可以设置默认值。
- 使用 Pydantic 模型:可以用Pydantic 模型作为请求体,可做为查询参数的数据类型,自动验证和解析客户端传入的 JSON 数据是否符合模型的定义,并将其转换为模型类型的实例。
- 数据转换和序列化:Pydantic 模型可以自动将数据转换为特定类型(例如 JSON)或反向序列化。
依赖项
- 定义和功能:函数,可以使用与路由处理函数相同参数的函数。用于在路由处理函数执行前或后运行的可复用的函数和逻辑,执行通用逻辑,如身份验证、数据库连接等。
- 类型:
预处理依赖项(Before): 在路由处理函数执行前运行,用于预处理输入数据,验证请求等。
后处理依赖项(After): 在路由处理函数执行后运行,用于执行一些后处理逻辑,如日志记录等。 - 依赖注入过程:
定义依赖项函数:from fastapi import Depends,依赖项函数定义和普通Python函数基本相同。
路由处理函数使用依赖项:(查询参数: 数据类型 = Depends(依赖项函数名)),依赖项函数处理结果返回给路由处理函数,做为入参使用。 - 注意:
1 可以使用多个依赖项函数,依赖项函数之间可以这种依赖和继承。
2 异步依赖项: 依赖项函数和路由处理函数可以设置为异步,允许在它们内部执行异步操作
表单数据处理
- 定义:接收和处理用户通过 HTML 表单提交的数据。
- 声明表单数据模型:
- 使用from fastapi import Form,用Form()定义查询参数的默认类型。
- 使用 Pydantic 模型声明,使用from pydantic import Field, 用Field()类型声明每个表单字段,做默认类型,可以添加相应的验证规则。
- 接收表单数据:在路由处理函数中,使用Form()类型接收表当数据,并和Pydantic 模型字段一一对应,实现表单数据验证和转换。
- 处理文件上传:使用from fastapi import File, UploadFile,如果表单包含文件上传,使用 UploadFile 类型处理,可以将文件的相关信息包装在 UploadFile 对象。
简单CRUD API样例
- 数据模型, 首先,定义Item数据模型:
1 | from pydantic import BaseModel |
- 存储数据, 在这个示例中,我们将使用一个简单的字典来存储数据:
1 | items = {} |
- 创建(Create)创建一个新的item:
1 | @app.post("/items/", response_model=Item) |
- 读取(Read), 读取一个item:
1 | @app.get("/items/{item_id}", response_model=Item) |
- 读取所有items:
1 | @app.get("/items/", response_model=List[Item]) |
- 更新(Update)更新一个item:
1 | @app.put("/items/{item_id}", response_model=Item) |
- 删除(Delete)删除一个item:
1 | @app.delete("/items/{item_id}", response_model=Item) |
使用注意
当使用uvicorn命令在本地(排查防火墙问题)正常启动API应用程序后发现,路径和端口调用没有反应,或者无法同时访问其他路由,或者修改完文件和重载后,交互式文件不能立即修改反应在界面上,可能是存在8000等端口占用的问题,导致后续对8000端口的请求在排队中。
排查方法:
使用命令检查端口占用情况:
Linux/macOS: sudo lsof -i 8000,检查LISTEN的端口状态,如果端口未被占用,则不会有输出。
Windows:netstat -ano | findstr :8000 ,检查LISTENING的端口状态,如果端口未被占用,则不会有输出
或者使用不同端口调度api服务:uvicorn main:app –reload –port 8001,然后尝试访问 http://127.0.0.1:8001/。
启动 Uvicorn,添加日志级别信息,查看日志输出:uvicorn main:app –reload –log-level debug
在控制台手动测试API服务端点命令:curl http:127.0.0.1:端口/在代码开发过程中,要注意确保服务端关闭的情况下,同时释放占用的端口。请求能快速反馈,没有长时间、执行耗时的阻塞或者耗时操作。FasfAPI内置支持使用信号来优雅关闭服务器并释放端口(signal库)
端口关闭方法:
操作系统 命令 含义 linux/macOS 终端窗口+kill -9 进程标识符 -9 表示强制终止进程 Windows 命令提示符+taskkill /PID 占用进程号 /F /PID 表示进程标识符,/F表示强制结束进程 TCP协议连接状态含义:
名称 含义 说明 LISTENING 端口正在监听连接请求 服务端已启动,服务端在等待客户端发起的连接请求 CLOSE_WAIT 连接一方已收到关闭请求,在等待对端关闭连接 表示客户端关闭连接,服务器还没有处理完成这些连接,需要调度close()等来关闭连接 TIME_WAIT 连接已关闭,在等待一段时间后所有数据包都已传输完成 TIME_WAIT通常是正常的,如果有大量的TIME_WAIT状态,就需要调整系统参数来优化
参考文献
[1] FastAPI教程
[2] 轻松上手Python的Web神器:FastAPI教程
[3] FastAPI 用户指南
[4] HTTP 教程