什么是 FastAPI?构建 API 的实用指南
FastAPI 是一个现代的 Python 框架,用于快速构建 API,支持类型注解、验证并自动生成 OpenAPI 文档。学习基础概念与使用场景。

FastAPI 一分钟速览:简单定义
FastAPI 是一个用于快速构建 Web API 的 Python 框架,代码清晰且能自动生成文档。你编写小函数(称为“端点”),声明 API 接受什么数据并返回什么,FastAPI 会处理网络方面的细节——路由、验证和生成 JSON 响应。
什么是 API?一个简单示例
API 是一组 URL,让一个软件与另一个软件对话。
例如,手机上的天气应用可能会调用像 GET /weather?city=Berlin 这样的 URL。服务器返回结构化数据(通常是 JSON),例如温度和天气预报。手机应用无需直接访问服务器的数据库——它只请求 API 并展示结果。
FastAPI 帮助你在 Python 中创建这些 URL 和响应。
FastAPI 适合谁?
- 初学者:想要一种现代、带引导性的方式来构建 API,而不写大量样板代码。
- 独立开发者:需要快速推进同时保持代码可读性。
- 团队:构建生产服务,受益于强验证、一致契约和优秀文档。
你不需要成为异步专家就能开始;可以先写简单端点,随着成长再采用更高级的模式。
本指南你将学到的内容
- FastAPI 与其它 Python API 选项的不同点
- 请求与响应如何工作(以及“async”真正的含义)
- 数据如何用 Pydantic 验证
- FastAPI 如何生成 OpenAPI 文档(Swagger UI 和 ReDoc)
- 如何用依赖、安全、测试和部署基础来组织应用
FastAPI 为什么流行
FastAPI 迅速流行起来,是因为它减少了构建 Python API 时常见的摩擦点。
它解决了常见的 API 痛点
传统 API 项目通常以缓慢的设置和大量“管道化”开始:
- 手动编写(并保持同步)请求解析、验证和错误消息
- 不清晰的 API 契约——这个端点到底接受并返回什么?
- 文档滞后于代码,尤其是团队成长时
FastAPI 的核心特性直接针对这些问题,因此团队可以把更多时间花在设计端点上,而不是与框架样板斗争。
类型注解让代码像契约一样工作
FastAPI 大量依赖 Python 的类型注解。当你声明某字段是 int、可选或某种列表时,FastAPI 会利用这些信息来验证输入并塑造输出。
这减少了“字符串化类型”的错误(例如在某处把 ID 当作文本,在另一个地方当作数字),并鼓励端点行为的一致性。它仍然是 Python,但函数签名中内置了更清晰的期望。
自动文档帮助团队更快推进
因为 API 架构源自代码,FastAPI 可以自动生成交互式文档(OpenAPI + Swagger UI/ReDoc)。这对协作很重要:前端开发、QA 和集成方可以探索端点、尝试请求并看到精确模型,而不需等待单独的文档工作。
流行,但不是万能的灵丹妙药
FastAPI 无法修复设计不良的 API。你仍然需要良好的命名、版本控制、错误处理和安全决策。它提供的是一条更清晰的路径,从“想法”走向“定义明确的 API”,减少沿途的意外情况。
你需要理解的关键概念
理解 FastAPI 的几个核心思想后,它会显得很直接。你不需要记住内部实现——只要识别日常会用到的移动部分。
FastAPI 是一个框架
“框架”是一组工具和约定,用于在不从零开始的情况下构建 API。FastAPI 为常见的 API 任务提供“管道”:定义端点、读取输入、返回输出、处理错误,以及将代码组织成可维护结构。
路由:如何定义端点
路由 是将 URL 和 HTTP 方法映射到一段 Python 代码的方式。
例如,你可能会将 GET /users 路由到“列出用户”,将 POST /users 路由到“创建用户”。在 FastAPI 中,通常用像 @app.get(...) 和 @app.post(...) 这样的装饰器定义路由,这样可以很容易一目了然地看到你的 API 提供了什么。
请求与响应
每次 API 调用都是一个 请求(客户端发送的内容)和一个 响应(服务器返回的内容)。
FastAPI 帮助你:
- 从路径(
/users/{id})、查询字符串(?page=2)、请求头和请求体中读取数据 - 返回带有正确状态码的结构化 JSON 响应(例如
200、201、404)
ASGI(高层次)
FastAPI 运行在 ASGI 上,这是现代 Python Web 服务器的一个标准。实际上,这意味着 FastAPI 设计用于高效处理大量连接,并且可以在需要时支持长连接(例如 WebSockets)——而无需你手动管理底层网络。
类型注解:不仅仅是“好看”
在 FastAPI 中,Python 类型注解(如 str、int、list[Item])不只是文档——它们是重要的输入。FastAPI 使用它们来理解你期望的数据、将传入值转换为正确类型,并产生更清晰、更可预测的 API。
用 Pydantic 模型做验证
Pydantic 模型让你在一个地方定义数据的形状(字段、类型、可选值)。FastAPI 使用这些模型来验证传入的 JSON、用有帮助的错误信息拒绝无效输入,并一致地序列化输出——因此即使客户端发送混乱数据,你的 API 也能更可靠地表现。
FastAPI 如何处理请求与响应
FastAPI 应用围绕 端点 构建:一个 URL 路径加上一个 HTTP 方法。把端点想象成“客户端要求什么”和“它如何要求”的结合。例如,客户端可能 GET /users 来列出用户,或 POST /users 来创建用户。
端点 = 路径 + 方法
路径是路由,方法是动作:
GET /products→ 获取数据POST /products→ 发送数据以创建资源PUT /products/123→ 替换/更新资源DELETE /products/123→ 删除资源
路径参数 vs 查询参数
FastAPI 将 URL 中属于路径的数据与作为可选“过滤器”的数据区分开来。
- 路径参数:包含在 URL 结构中。示例:
GET /users/42→42是用户 ID。 - 查询参数:在
?之后追加,通常是可选的。示例:GET /users?limit=10&active=true→limit和active控制结果返回方式。
用于 JSON 有效载荷的请求体
当客户端发送结构化数据(通常是 JSON)时,这些数据放在请求体中,通常用于 POST 或 PUT。
示例:POST /orders,JSON 为 { "item_id": 3, "quantity": 2 }。
响应模型与一致输出
FastAPI 可以返回普通的 Python 对象(例如 dict),但它在你定义 响应模型 时更有优势。该模型充当契约:字段一致、额外数据可被过滤、类型被强制。结果是更干净的 API——客户端知道预期内容,你也避免了会破坏集成的“惊喜”响应。
FastAPI 中的 Async:是什么以及何时有用
“Async”(异步)是一种在大量等待时更高效处理多个请求的方式。
日常类比:等待 I/O
想象一个咖啡师接单。如果咖啡师在机器运行时必须一直站着空等,他们能服务的顾客会很少。更好的方式是:启动咖啡机,然后在等待时接下一个订单。
异步就是这样工作的。你的 FastAPI 应用可以启动一个需要等待的操作(例如网络请求或数据库查询),在等待时去处理其他进入的请求。
异步最有用的场景
当你的 API 做大量 I/O(输入/输出)工作时,异步最有帮助——即花时间在等待而不是“计算”。常见示例:
- 调用数据库(尤其是通过网络)
- 调用外部服务(支付提供商、地图、邮件 API)
- 读/写文件或与对象存储通信
如果端点经常等待这些操作,异步可以提高吞吐量并减少请求在负载下堆积的可能性。
什么时候异步不太重要
异步并不是万能的加速按钮。如果端点主要是 CPU 密集型——比如调整大图像大小、运行数据科学计算或加密大负载——异步本身不会让计算更快。在这些情况下,通常需要不同策略(后台任务、进程池或横向扩展)。
好消息:同步代码也能工作
你不必重写所有代码来使用 FastAPI。可以编写常规(同步)路由函数,FastAPI 也能正常运行。许多项目混合使用两种风格:对简单端点保持同步,而在明显受益的场景(通常围绕数据库调用或外部 HTTP 请求)使用 async def。
使用 Pydantic 做数据验证与序列化
验证是外部世界与代码之间的检查点。当 API 接受输入(JSON 体、查询参数、路径参数)时,你希望在写入数据库、调用其他服务或触发业务逻辑之前,确保数据完整、类型正确且在合理范围内。
FastAPI 依赖 Pydantic 模型来完成这件事。你描述“良好数据”的样子一次,FastAPI 会自动:
- 提前拒绝错误输入
- 在可能时转换类型(例如把 "42" 变为整数)
- 返回一致的 JSON 响应(序列化)
提前捕获错误输入(并给出清晰错误)
如果客户端发送了错误格式的数据,FastAPI 会以 422 Unprocessable Entity 响应,并返回结构化的错误载荷,指出确切字段和原因。这让客户端开发者更容易快速修复请求,而不必猜测。
常见验证示例
下面是一个小模型,展示了必填字段、类型、最小/最大约束和格式:
from pydantic import BaseModel, EmailStr, Field
class UserCreate(BaseModel):
email: EmailStr
age: int = Field(ge=13, le=120)
username: str = Field(min_length=3, max_length=20)
- 必填字段:
email必须存在。 - 类型:
age必须是整数。 - 最小/最大:
age限制在 13–120。 - 格式:
EmailStr强制要求是有效的邮箱格式。
序列化:返回干净且可预测的 JSON
相同的模型也可以塑造输出,这样你的 API 响应就不会意外泄露内部字段。你返回 Python 对象;FastAPI(通过 Pydantic)把它们转换为具有正确字段名和类型的 JSON。
自动 API 文档:OpenAPI、Swagger UI、ReDoc
FastAPI 最实用的特性之一是它会自动为你生成 API 文档——基于你已编写的代码。
OpenAPI:机器可读的 API 契约
OpenAPI 是以结构化格式(通常为 JSON)描述 API 的标准。把它看作一个列出:
- 哪些端点存在(例如
GET /users/{id}) - 它们接受哪些参数
- 请求体应是什么样子
- 可以预期的响应和错误格式
由于它是机器可读的,工具可以用它来生成测试客户端、验证请求并保持团队一致。
Swagger UI 与 ReDoc:开箱即用的交互式文档
FastAPI 自动提供两个面向人的文档页面:
- Swagger UI(交互式):可以在浏览器中直接尝试端点,填写参数、发送请求并查看响应。
- ReDoc(可读型):清晰的参考式文档页面。
在典型的 FastAPI 项目中,你会在:
/docs(Swagger UI)/redoc(ReDoc)
与代码保持同步的文档
当你更改路径参数、请求模型、响应模型或验证规则时,OpenAPI 模式(和文档页面)会自动更新。无需单独维护文档步骤。
为什么这能加速前端和 QA 的工作
- 前端 开发人员可以立即探索端点并了解必填字段,而不必等待手写规格。
- QA 可以快速测试边界情况(缺失字段、错误类型)并查看精确的错误响应。
- 每个人共享同一个事实来源:正在运行的 API 及其 OpenAPI 契约。
你的第一个 FastAPI 应用(概念演练)
FastAPI 应用可以很小却仍然“真实”。你定义一个名为 app 的 Python 对象,添加几个路由,然后运行本地服务器在浏览器中试用。
1)最小的 “hello” 端点
下面是最小的有用示例:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"message": "Hello, FastAPI"}
就是这样:一个返回 JSON 的路由(GET /)。
2)添加简单的创建/读取项端点(内存存储)
为了让它更像一个 API,我们把项存储在一个列表中。这不是数据库——服务器重启后数据会重置——但它很适合学习。
from fastapi import FastAPI
app = FastAPI()
items = []
@app.post("/items")
def create_item(name: str):
item = {"id": len(items) + 1, "name": name}
items.append(item)
return item
@app.get("/items")
def list_items():
return items
现在你可以:
POST /items?name=Coffee来添加一项GET /items来检索列表
3)典型的小型项目布局
一个常见的入门结构是:
main.py(创建app并定义路由)requirements.txt或pyproject.toml(依赖)
4)本地运行(概念)
通常你会:
- 安装依赖(FastAPI + 一个 ASGI 服务器,比如 Uvicorn)
- 启动开发服务器(例如:
uvicorn main:app --reload) - 打开
http://127.0.0.1:8000并尝试端点
依赖与可重用构建块
FastAPI 的“依赖”是端点需要的共享输入——比如数据库会话、当前登录用户、应用设置或常见查询参数。你不必在每个路由中手动创建或解析这些东西;定义一次,FastAPI 在需要时会提供它们。
什么是依赖(通俗解释)
依赖通常是一个返回值的函数(或类),你的端点可以使用该值。FastAPI 会为你调用它,根据其参数推断所需内容,并把结果注入到路径操作函数中。
这通常被称为依赖注入,但你也可以把它理解为:“声明你需要什么,FastAPI 自动连线”。
为什么它减少重复
没有依赖时,你可能会:
- 在每个端点中打开/关闭数据库连接
- 在各处重复身份验证检查
- 在多个路由中重复解析相同的分页参数
使用依赖后,你可以把这些逻辑集中。如果以后更改如何创建 DB 会话或如何加载当前用户,只需更改一处,而不是数十个端点。
常见的依赖示例
- 数据库会话:为每次请求创建会话并可靠地关闭它。
- 设置/配置:提供基于环境的设置而无需手动传递。
- 分页:重用
page/limit的解析与验证。 - 认证用户:从令牌中检索当前用户并执行权限检查。
依赖如何插入端点
下面是许多 FastAPI 应用中常见的概念模式:
from fastapi import Depends, FastAPI
app = FastAPI()
def get_settings():
return {"items_per_page": 20}
@app.get("/items")
def list_items(settings=Depends(get_settings)):
return {"limit": settings["items_per_page"]}
你用 Depends(...) 声明依赖,FastAPI 会把其结果传入你的端点参数。相同方法也适用于更复杂的构建块(如 get_db() 或 get_current_user()),帮助你的代码随着 API 增长保持清晰。
安全基础:认证与授权
FastAPI 不会“自动保护”你的 API——你需要选择方案并把它连入端点。好消息是,FastAPI 通过其依赖系统提供了便于实现常见安全模式的构建块。
认证 vs 授权
认证 回答:“你是谁?” 授权 回答:“你被允许做什么?”
例如:用户可能已通过认证(有效登录/令牌),但仍未被授权访问仅限管理员的路由。
常见的认证方法(高层次)
- API 密钥:适用于服务到服务的简单访问,通常放在请求头(如
X-API-Key)。要管理轮换与撤销。 - OAuth2:一种常见的委托访问标准;适合“使用…登录”或将认证与 API 分离的场景。
- JWT(JSON Web Tokens):常用作 Bearer 令牌。适合无状态 API,但需处理过期、签名密钥与撤销策略。
FastAPI 通过像 fastapi.security 的工具支持这些模式,并在 OpenAPI 中清晰记录它们。
密码处理基础
如果你存储用户密码,绝不要存明文。应存储带盐的慢哈希(例如通过成熟库使用 bcrypt/argon2)。还应考虑速率限制和账户锁定策略。
一句谨慎的提醒
安全关乎细节:令牌存储、CORS 设置、HTTPS、密钥管理以及对每个敏感端点的正确授权检查。把内置助手当作起点,并在投入生产前通过评审和测试验证你的方案。
测试 FastAPI 应用
测试是把 FastAPI 的“在我机器上可运行”承诺变成可发布信心的地方。好消息是:FastAPI 构建于 Starlette 之上,因此你可以获得强大的测试工具,而无需大量配置。
单元测试 vs 集成测试
单元测试 聚焦小片段:一个计算函数、加载当前用户的依赖或与数据库交互(通常被 mock)的服务方法。
集成测试 则端到端地测试 API:调用端点并断言完整的 HTTP 响应。这些能捕捉路由错误、依赖注入问题和验证缺陷。
健全的测试套件通常单元测试更多(运行快),集成测试较少(置信度高)。
TestClient 思想
FastAPI 应用可使用 Starlette 的 TestClient 像客户端一样测试你的应用(进程内发送请求——无需服务器)。
from fastapi.testclient import TestClient
from app.main import app
client = TestClient(app)
def test_healthcheck():
r = client.get("/health")
assert r.status_code == 200
要测试的事项(实用清单)
测试用户和其他系统依赖的事项:
- 状态码(200 vs 201 vs 404 vs 422)
- 验证错误(缺失字段、错误类型、额外字段)
- 响应形状(键存在、类型正确、空列表处理)
- 边界情况(零结果、大输入、临界日期)
- 认证用例(无令牌、令牌过期、角色不足)
保持测试快速且可重复
使用可预测数据,隔离外部服务(mock 或使用测试数据库),并避免测试间共享状态。快速的测试会被经常运行;慢速测试往往会被跳过。
部署 FastAPI:实用选项与清单
将 FastAPI 应用上线主要是选择合适的“运行器”并加入一些生产必需项。
开发服务器 vs 生产服务器
当你在本地运行 uvicorn main:app --reload 时,这是开发设置:自动重载、详细错误信息和优先便利性的设置。
在生产中,通常无 --reload 运行 Uvicorn,常配合进程管理器(如使用 Uvicorn worker 的 Gunicorn)或放在反向代理后面。目标是稳定性:可控重启、可预测性能和更安全的默认值。
用环境变量进行配置
常见模式:
- 将秘密与环境相关值(数据库 URL、API 密钥、允许的来源)放在环境变量中。
- 在代码中保留本地使用的合理默认值。
- 在启动时加载并验证设置(常用 Pydantic 的设置模型)。
这让同一份代码可部署到多个环境,而无需编辑文件。
常见部署目标(快速概览)
- 容器(Docker/Kubernetes):适合可重复构建与扩缩。
- 虚拟机:简单灵活;适合自主管理服务器。
- 无服务器:适合小型 API;注意冷启动和平台限制。
实用部署清单
在你称之为“完成”之前,确认你具备:
- 日志:结构化日志、请求 ID(如需)和按环境配置的日志级别。
- 健康检查:如
/health,便于监控和负载均衡器检测。 - 错误处理:一致的 JSON 错误响应;不要向用户暴露堆栈追踪。
- 超时与限制:请求体大小、工作进程超时与必要时的速率限制。
- 文档策略:决定是否公开 Swagger UI/ReDoc 或对其进行限制。
当你从“本地可用”迈向“可交付”时,把 FastAPI 的 OpenAPI 输出与自动化工作流配对也很有帮助——例如生成客户端、在 CI 中验证请求并一致地部署。像 Koder.ai 这样的工具也可在这个阶段发挥作用:你可以在聊天中描述想要的 API,快速迭代端点和模型,然后导出源码以纳入常规评审/部署流程。
何时使用 FastAPI(何时不使用)
当你希望以干净、现代的方式在 Python 中构建 REST API,尤其是你重视清晰的请求/响应模型和随着 API 增长保持可预测行为时,FastAPI 是一个很强的选择。
适合的场景
FastAPI 在以下情况表现优异:
- 内部服务:团队需要快速迭代、可读端点和服务间共享契约时。
- 公开 API:受益于严格输入验证与一致错误处理的场景。
- 微服务:小型、专注的 API 独立部署时。
- 原型与 MVP:想要快速推进同时保持结构(验证 + 文档)。
何时其他工具更合适
FastAPI 并非总是最简单的答案:
- 如果你只是写一个一次性脚本或很小的 webhook 处理器,使用更轻量的工具(甚至直接用 Python)可能足够。
- 如果项目需要完整的 Django“内置电池”栈(ORM 约定、管理后台、模板、成熟生态模式),Django 或 Django REST Framework 可能会减少决策与胶合代码。
关于性能的现实话
FastAPI 在实践中可以非常快,但性能取决于你的数据库调用、网络延迟和业务逻辑。预计在典型 API 工作负载中能获得良好的吞吐与延迟——但不要指望单靠框架就能“修复”缓慢的 I/O 或低效查询。
下一步
如果 FastAPI 听起来合适,下一步可聚焦路由模式、Pydantic 模型、数据库集成、后台任务和基本认证。
一个实用路径是先构建一小组端点,然后随着 API 增长扩展可重用依赖与测试。如果想加速早期脚手架(路由、模型与第一个可部署结构),可以考虑一种基于“规划模式”的快速迭代工作流——例如在单一规范上映射端点并从中迭代。这正是像 Koder.ai 这类工具有用的地方:你可以从聊天中原型一个以 API 为驱动的应用,然后在准备好运行时导出并纳入标准项目结构。
常见问题
用通俗的话说,什么是 FastAPI?
FastAPI 是一个用于构建 API 的 Python web 框架,减少样板代码。你编写端点函数(例如 @app.get("/users")),FastAPI 负责路由、请求解析、验证和 JSON 响应。
一个关键优点是你的类型注解和 Pydantic 模型充当了 API 接受和返回内容的显式契约。
什么是 API?它与 FastAPI 有何关系?
API 是一组 URL(端点),其他软件可以调用这些 URL 来交换数据。
例如,客户端可能会用 GET /weather?city=Berlin 请求天气数据,服务器返回结构化的 JSON。客户端无需直接访问数据库——只需使用 API 返回的数据即可。
FastAPI 中路由和 HTTP 方法如何工作?
路由将 HTTP 方法 + 路径映射到一个 Python 函数。
在 FastAPI 中通常使用装饰器:
@app.get("/items")用于读取操作@app.post("/items")用于创建操作@app.put("/items/{id}")用于更新/替换@app.delete("/items/{id}")用于删除
这使得从代码中直接查看 API 面向变得容易。
路径参数和查询参数有什么区别?
路径参数是 URL 结构的一部分,通常用于标识特定资源(必需)。
- 路径示例:
GET /users/42→42是路径参数
查询参数附加在 ? 之后,通常是可选的过滤或控制项。
- 查询示例:
GET /users?limit=10&active=true→limit、active是查询参数
FastAPI 如何使用 Pydantic 进行数据验证?
Pydantic 模型定义了数据的形状和规则(类型、必填字段、约束)。FastAPI 使用它们来:
- 验证入站请求
- 尽可能地转换类型(例如将字符串
"42"转为整数) - 返回一致、格式良好的 JSON 响应
如果验证失败,FastAPI 通常返回 422 Unprocessable Entity 并说明哪个字段有问题。
FastAPI 如何生成自动化 API 文档?
FastAPI 会根据你的端点、类型注解和模型自动生成 OpenAPI 模式。
通常你可以得到交互式文档:
- 在
/docs查看 Swagger UI - 在
/redoc查看 ReDoc
由于模式源自代码,随着参数和模型的变化,文档也会自动保持同步。
什么时候应该在 FastAPI 中使用 async 端点?
当你的端点大量花时间在 I/O 等待上(数据库调用、外部 HTTP 请求、文件/对象存储)时,使用 async def 更合适。
在以下情况使用普通 def:
- 代码简单且同步
- 调用的库不支持 async
- 工作主要是 CPU 密集型(async 无法加速计算)
在同一个应用中混合同步和异步端点很常见。
什么是 FastAPI 依赖项?它们有什么用?
依赖项是 FastAPI 可以通过 Depends() 注入到端点中的可重用“构建块”。
它们常用于:
- 每请求的数据库会话
- 身份验证:加载当前用户并执行权限检查
- 共享查询解析(分页、过滤)
- 应用设置/配置
这样可以减少重复并将横切逻辑集中到一个地方,以便只需在一处修改即可影响所有端点。
在构建 FastAPI 时,我需要了解的安全基础是什么?
FastAPI 不会默认为你的 API 提供安全保护——你需要选择方案并在端点中应用。常见做法包括:
- API 密钥(通常通过请求头发送)
- OAuth2 流程
- Bearer 令牌(常见为 JWT)
另外注意基础安全要点:
- 切勿以明文存储密码;使用带盐的慢哈希(如 bcrypt/argon2)
- 将认证(你是谁)与授权(你能做什么)区分开来
- 在浏览器客户端场景下使用 HTTPS 并检查 CORS 设置
如何在实践中测试和部署 FastAPI 应用?
测试时可以使用 FastAPI/Starlette 提供的 TestClient 在进程内调用你的 API(无需启动服务器)。
实践中要断言的要点包括:
- 状态码(200/201/404/422)
- 验证行为(缺失字段、错误类型)
- 响应形状(字段存在、类型正确)
- 身份验证场景(无令牌、过期令牌、权限不足)
部署时运行 ASGI 服务器(通常是 Uvicorn;在需要时可配合 Gunicorn 或反向代理),并添加运行所需的生产要素,如日志、健康检查(如 /health)、超时和基于环境的配置。