一、为什么选择 FastAPI?
在现代 Web 开发领域,API 服务的构建速度与性能至关重要。FastAPI 作为一个基于 Python 的高性能 Web 框架,凭借其原生异步支持、自动文档生成和强大的类型提示系统,迅速成为开发者手中的利器。
1.1 异步性能的革命性提升
FastAPI 原生支持异步编程,这意味着在处理 I/O 密集型任务时,它可以极大提升并发能力。我们通过一个简单的对比实验就能看出差距:
-
同步方式:顺序执行 10 次 time.sleep(1),总耗时超过 10 秒
import time
from fastapi import FastAPI
app = FastAPI()
@app.get("/sync")
def func_sync():
start = time.time()
for i in range(10):
time.sleep(1) # 同步阻塞,每次等待1秒
end = time.time()
return {"time": f"{end-start:.2f}s"} # 耗时约 10 秒+
-
异步方式:使用 asyncio.gather 并发执行 10 次 asyncio.sleep(1),总耗时仅约 1 秒
import asyncio
from fastapi import FastAPI
app = FastAPI()
@app.get("/async")
async def func_async():
start = time.time()
tasks = [asyncio.sleep(1) for i in range(10)] # 异步休眠,不阻塞事件循环
await asyncio.gather(*tasks) # 并发执行所有休眠任务
end = time.time()
return {"time": f"{end-start:.2f}s"} # 耗时约 1 秒
这一差异在高并发场景下会被无限放大,FastAPI 的异步特性让它能够轻松应对海量请求。
1.2 开发效率的全面提速
除了性能优势,FastAPI 在开发体验上也做到了极致:
-
类型提示与自动校验:基于 Pydantic,只需定义数据模型,框架自动完成参数验证,告别手写校验代码。
from pydantic import BaseModel
class User(BaseModel):
username: str
password: str
@app.post("/register")
async def register(user: User):
# 自动校验 username 和 password 是否为字符串,且不为空
return user
-
交互式 API 文档:启动服务后,访问 /docs 即可获得 Swagger UI 风格的在线文档,支持直接在浏览器中调用和测试接口,前后端协作效率倍增。
1.3 三大核心优势总结
| 异步性能高 | 原生 async/await 支持,并发能力出众 |
| 开发效率高 | 类型提示 + 自动校验,减少冗余代码 |
| 自动生成文档 | 交互式文档,即写即用,沟通零成本 |
官网地址:FastAPI – FastAPI – FastAPI 框架
二、第一个 FastAPI 程序
2.1 环境准备与项目创建
在开始编码之前,强烈建议为每个项目创建独立的虚拟环境。这可以隔离项目依赖,避免不同项目间的包版本冲突,保持全局 Python 环境的干净与稳定。
创建虚拟环境后,安装 FastAPI 和 ASGI 服务器 Uvicorn:
pip install fastapi uvicorn
2.2 编写最小化应用
创建一个 main.py 文件,写入以下代码:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
2.3 运行与访问
2.3.1使用 Uvicorn 启动服务:
uvicorn main:app –reload
-
main:Python 文件名
-
app:FastAPI 实例对象
-
–reload:开启热重载,代码变动后自动重启服务器(仅开发环境使用)
启动成功后,访问以下地址:
-
接口地址:http://127.0.0.1:8000
-
交互式文档:http://127.0.0.1:8000/docs
2.3.2使用Pycharm图形化页面启动

三、路由:URL 与函数的映射关系
3.1 路由的基本概念
路由(Route)本质上就是 URL 地址 与 处理函数 之间的映射表。当用户访问某个特定网址时,服务器根据路由规则找到对应的函数并执行,最终将结果返回给客户端。
在 FastAPI 中,路由通过装饰器模式定义,非常直观:
@app.get("/user/hello")
async def say_hello():
return {"msg": "我正在学习 FastAPI ….."}
3.2 练习:定义一个简单路由
需求:访问路径 /user/hello,响应 JSON 数据 {"msg":"我正在学习 FastAPI ….."}。
实现方式即上面代码所示,通过 @app.get 装饰器将路径与函数绑定。
from fastapi import FastAPI
app = FastAPI()
@app.get("/user/hello")
async def hello_fastapi():
return {"msg": "我正在学习 FastAPI ….."}
四、参数详解
同一段接口逻辑,往往需要根据客户端传入的不同参数返回差异化的数据。参数就是客户端请求时附带的额外信息,其作用是让接口具备动态交互能力。
4.1 路径参数(Path Parameters)
4.1.1 基本用法
路径参数是 URL 路径的一部分,用于指向唯一的、特定的资源。例如 /book/{id}。
@app.get("/book/{id}")
async def get_book(id: int):
return {"id": id, "title": f"这是第{id}本书"}
4.1.2 类型注解与校验(Path)
FastAPI 允许通过 Path 函数为路径参数添加额外校验规则(如大小限制、描述等)。
from fastapi import FastAPI, Path
@app.get("/book/{id}")
async def get_book(id: int = Path(…, gt=0, le=100, description="图书ID")):
return {"id": id, "title": f"这是第{id}本书"}
Path 常用参数:
| …(必填) | 表示该参数必须提供 |
| gt / ge | 大于 / 大于等于 |
| lt / le | 小于 / 小于等于 |
| min_length / max_length | 字符串长度限制 |
| description | 参数描述 |
4.1.3 练习:路径参数校验
需求:定义两个接口,携带路径参数并使用 Path 校验:
-
接口1:新闻分类 id,范围为 1~100
-
接口2:新闻分类名称,长度为 2~10
代码实现:
from fastapi import FastAPI, Path
app = FastAPI()
# 接口1:分类ID校验
@app.get("/news/category/{cat_id}")
async def get_category_by_id(cat_id: int = Path(…, gt=0, le=100, description="分类ID")):
return {"category_id": cat_id, "name": f"分类{cat_id}"}
# 接口2:分类名称校验
@app.get("/news/category/name/{cat_name}")
async def get_category_by_name(cat_name: str = Path(…, min_length=2, max_length=10, description="分类名称")):
return {"category_name": cat_name}
4.2 查询参数(Query Parameters)
4.2.1 基本用法
查询参数位于 URL 的 ? 之后,格式为 k1=v1&k2=v2,常用于过滤、排序、分页等操作。在路径操作函数中,非路径参数的形参会被自动解释为查询参数。
@app.get("/news/news_list")
async def get_news_list(skip: int, limit: int = 10):
return {"skip": skip, "limit": limit}
访问示例:/news/news_list?skip=0&limit=20
4.2.2 类型注解与校验(Query)
使用 Query 函数为查询参数添加校验和描述。
from fastapi import FastAPI, Query
@app.get("/user")
async def get_user(user_id: int = Query(…, gt=0, description="用户ID")):
return {"user_id": user_id}
4.2.3 练习:查询参数校验
需求:设计接口查询图书,携带两个查询参数:
-
图书分类:默认值为 "Python 开发",长度限制 5~255
-
价格:范围 50~100
代码实现:
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/books/search")
async def search_books(
category: str = Query("Python 开发", min_length=5, max_length=255, description="图书分类"),
price: float = Query(…, ge=50, le=100, description="价格范围")
):
return {
"category": category,
"price": price,
"message": f"正在搜索 {category} 分类下价格约 {price} 元的图书"
}
4.3 请求体参数(Request Body)
4.3.1 基本用法
请求体位于 HTTP 请求的消息体(body)中,常用于创建或更新资源时携带大量结构化数据(通常为 JSON),对应 POST、PUT 等方法。在 FastAPI 中,通过 Pydantic 模型来定义请求体结构。
from pydantic import BaseModel
class User(BaseModel):
username: str
password: str
@app.post("/register")
async def register(user: User):
return user # FastAPI 自动解析 JSON 并转换为 User 实例
4.3.2 练习:定义请求体
需求:设计接口新增图书,图书信息包含:书名、作者、出版社、售价。
代码实现:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Book(BaseModel):
title: str
author: str
publisher: str
price: float
@app.post("/books")
async def create_book(book: Book):
return {
"message": "图书创建成功",
"book": book
}
4.3.3 高级校验(Field)
Pydantic 的 Field 函数可为模型字段添加更细致的校验(如长度、取值范围、默认值等)。
from pydantic import BaseModel, Field
class Book(BaseModel):
title: str = Field(…, min_length=2, max_length=20, description="书名")
author: str = Field(…, min_length=2, max_length=10, description="作者")
publisher: str = Field(default="超超出版社", description="出版社")
price: float = Field(…, gt=0, description="售价")
4.3.4 练习:请求体参数校验
需求:设计接口新增图书,具体要求:
-
书名:不能为空,长度 2~20
-
作者:长度 2~10
-
出版社:默认值 "黑马出版社"
-
售价:不能为空,大于 0 元
完整代码:
from fastapi import FastAPI
from pydantic import BaseModel, Field
app = FastAPI()
class Book(BaseModel):
title: str = Field(…, min_length=2, max_length=20, description="书名")
author: str = Field(…, min_length=2, max_length=10, description="作者")
publisher: str = Field(default="黑马出版社", description="出版社")
price: float = Field(…, gt=0, description="售价")
@app.post("/books")
async def create_book(book: Book):
return {
"message": "图书创建成功",
"book": book
}
五、请求与响应
5.1 默认响应行为
FastAPI 默认将路径操作函数返回的 Python 对象(字典、列表、Pydantic 模型等)通过 jsonable_encoder 转换为 JSON 兼容格式,并包装为 JSONResponse 返回。
@app.get("/")
async def root():
return {"message": "hello world"} # 自动转为 JSON
5.2 多种响应类型
FastAPI 提供了丰富的响应类,用于返回非 JSON 数据,例如 HTML、纯文本、文件流、重定向等。
| JSONResponse | 默认,返回 JSON | return {"key": "value"} |
| HTMLResponse | 返回 HTML 内容 | return HTMLResponse("<h1>标题</h1>") |
| PlainTextResponse | 返回纯文本 | return PlainTextResponse("text") |
| FileResponse | 返回文件下载 | return FileResponse(path) |
| StreamingResponse | 流式响应 | 生成器函数返回数据 |
| RedirectResponse | 重定向 | return RedirectResponse(url) |
5.3 设置响应类型的方式
方式一:在装饰器中指定 response_class
适用于固定返回类型(如 HTML、纯文本)。
from fastapi.responses import HTMLResponse
@app.get("/html", response_class=HTMLResponse)
async def get_html():
return "<h1>这是标题</h1>" # 自动以 HTML 格式返回
方式二:直接返回响应对象
适用于文件下载、图片、流式响应等场景。
from fastapi.responses import FileResponse
@app.get("/file")
async def get_file():
file_path = "./files/1.jpeg"
return FileResponse(file_path)
5.4 自定义响应数据格式(response_model)
通过装饰器的 response_model 参数,使用 Pydantic 模型严格约束输出格式,既保证数据结构的统一性,也能过滤掉模型中未定义的字段,保障数据安全。
from pydantic import BaseModel
class News(BaseModel):
id: int
title: str
content: str
@app.get("/news/{id}", response_model=News)
async def get_news(id: int):
# 即使返回多余字段,response_model 也会自动过滤,只保留 id, title, content
return {
"id": id,
"title": f"这是第{id}条新闻",
"content": "这是一条重要新闻",
"extra_field": "这个字段不会被返回"
}
5.5 练习:综合响应类型
需求:分别实现返回 HTML、纯文本、文件下载的接口。
代码实现:
from fastapi import FastAPI
from fastapi.responses import HTMLResponse, PlainTextResponse, FileResponse
app = FastAPI()
@app.get("/html", response_class=HTMLResponse)
async def return_html():
return "<h2>欢迎访问 FastAPI 示例</h2><p>这是 HTML 响应</p>"
@app.get("/text", response_class=PlainTextResponse)
async def return_text():
return "这是纯文本响应内容"
@app.get("/download")
async def download_file():
# 假设当前目录下存在 files/sample.pdf
return FileResponse("files/sample.pdf", filename="sample.pdf")
六、异常处理
对于客户端引发的错误(如资源未找到、认证失败),应使用 fastapi.HTTPException 来中断正常流程并返回标准错误响应。
from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.get("/news/{id}")
async def get_news(id: int):
id_list = [1, 2, 3, 4, 5, 6]
if id not in id_list:
raise HTTPException(status_code=404, detail="当前id不存在")
return {"id": id, "title": f"新闻{id}"}
访问 /news/10 将返回 404 状态码和错误详情 {"detail": "当前id不存在"}。
七、总结
| 异步性能 | 使用 async/await 可显著提升 I/O 密集型接口的并发能力 |
| 路由 | 通过装饰器 @app.get() 等将 URL 映射到处理函数 |
| 路径参数 | URL 的一部分,使用 Path 校验,如 /book/{id} |
| 查询参数 | URL ? 之后,使用 Query 校验,如 ?skip=0&limit=10 |
| 请求体参数 | HTTP body 中的 JSON 数据,使用 Pydantic 模型 + Field 校验 |
| 响应类型 | 默认 JSON,可通过 response_class 或直接返回响应对象切换类型 |
| 响应模型 | 使用 response_model 约束输出格式,过滤多余字段 |
| 异常处理 | 使用 HTTPException 抛出标准化错误响应 |
FastAPI 集高性能、高效率开发与自动文档于一身,是当前 Python Web API 开发的首选框架。掌握上述基础知识点,即可快速构建可靠、规范的 RESTful 服务。下一步可深入中间件、依赖注入、数据库集成等高级主题,进一步提升实战能力。


