📚前言
📒FDE系列内容总纲:
🚄前置课程列表:
阶段一:
【FDE系列】阶段1Day 1:AI 层级关系 --- 四个嵌套的圈-CSDN博客
【FDE系列】阶段1Day 2:AI 三阶段发展史 --- 会认 → 会判断 → 会创造-CSDN博客
【FDE系列】阶段1Day 3:符号 AI vs 机器学习 --- 两条路线的本质区别-CSDN博客
【FDE系列】阶段1Day 4:Transformer 的历史意义 --- 2017 年的分水岭-CSDN博客
【FDE系列】阶段1Day 5:本周复习与自测 --- 检验你的 AI 认知地基-CSDN博客
【FDE系列】阶段1Day 6:Transformer 架构 --- 一张图纸盖出千千万万栋楼-CSDN博客
【FDE系列】阶段1Day 7:LLM 本质 --- 文字接龙机器-CSDN博客
【FDE系列】阶段1Day 8:Token --- 模型眼中的最小单位-CSDN博客
【FDE系列】阶段1Day 9:AI 幻觉 --- 为什么会一本正经地胡说八道-CSDN博客
【FDE系列】阶段1Day 10:上下文窗口 --- 模型的记忆力上限 + 本周复习-CSDN博客
【FDE系列】阶段1Day 11:Prompt --- 给模型立规矩-CSDN博客
【FDE系列】阶段1Day 12:Memory --- 让模型记住上下文
【FDE系列】阶段1Day 13:RAG --- 给模型配图书管理员-CSDN博客
【FDE系列】阶段1Day 14:Tool Use --- 让模型动手操作-CSDN博客
【FDE系列】阶段1Day 15:MCP --- 统一的工具接口标准 + 第三周复习-CSDN博客
【FDE系列】阶段1Day 16:什么是 FDE --- 把 AI 变成客户结果的人-CSDN博客
【FDE系列】阶段1Day 17:FDE vs 传统实施 --- 三大本质区别-CSDN博客
【FDE系列】阶段1Day 18:FDE 三重身份 + C6 胜任力模型-CSDN博客
【FDE系列】阶段1Day 19:七阶段行动路径 + 行业经验的价值-CSDN博客
【FDE系列】阶段1Day 20:阶段总结与产出物 --- 第一阶段收官-CSDN博客
阶段二:
【FDE系列】阶段2:Day 21:Python 环境搭建 --- 写出你的第一行代码-CSDN博客
【FDE系列】阶段2:Day 22:变量、数据类型、条件判断 --- Python 的"记忆"和"判断"-CSDN博客
【FDE系列】阶段2:Day 23:循环与函数 --- 让代码跑 100 遍、把逻辑打包复用-CSDN博客
【FDE系列】阶段2:Day 24:数据结构 --- 列表、字典、集合、元组-CSDN博客
【FDE系列】阶段2:Day 25:文件读写与 JSON --- 让程序连通外部数据(第一周收官)-CSDN博客
【FDE系列】阶段2:Day 26:模块化编程 --- 把代码拆成"抽屉柜"-CSDN博客
【FDE系列】阶段2:Day 27:异常处理与日志 --- 让程序"摔不烂、查得到"-CSDN博客
🚀阶段2·Day 28:FastAPI 入门 --- 把你的函数变成 API 服务
FDE 学习系列教程 · 第二阶段 · 第 2 周 · Day 3 预计时长:3 小时 | 难度:★★★☆☆ | 前置知识:Day 22-27(函数、模块、异常基础)
📌 一句话目标:理解 HTTP/API 的基本交互,用 FastAPI 写出可通过网址访问的接口,掌握路径参数、查询参数和自动文档------FDE 技术栈的主干正式登场。
🧑🤝🧑 老哥开场白
这周前两节课在给代码"精装修"。今天开始,干一件让你身价上涨的事:把 Python 函数变成网络服务。
回想第一阶段你调 Dify API 的经历:你发一段请求,它返回一个结果。你有没有好奇过------"服务端"是怎么收到请求、又怎么返回的?
今天你就坐到服务端这一侧来。学完你会发现:所谓 API 服务,本质就是"一个一直在运行的 Python 程序,等着别人通过网址来调用它的函数"。
之前:你写脚本 → 自己运行 → 看结果
今天:你写服务 → 启动后一直跑 → 浏览器/客户系统/AI Agent 通过 HTTP 来调用
👉 FastAPI 是目前 Python 世界最火的 API 框架(GitHub 80K+ Star),以"自带文档、写得少、自动校验"著称。今天新概念密集(HTTP、路由、参数),但每个都马上动手验证,别怕。
🌐 先搞懂 API 和 HTTP(3 分钟版)
用餐厅类比理解一切
你(客户端)去餐厅:
1. 招呼服务员,点菜(发起请求 Request)
2. 后厨按菜单做菜(服务器处理逻辑)
3. 服务员端菜上来(返回响应 Response)
HTTP 就是客户端和服务器之间"点菜---上菜"的规矩。
URL 就是"菜单位置"
http://localhost:8000/devices/A1
└──────┬──────┘ └────┬────┘ └──┬──┘
服务器地址 端口 路径(你要哪个功能)
-
localhost= 本机(你自己的电脑当服务器) -
8000= 门牌号(端口号),FastAPI 默认住 8000 -
/devices/A1= 路径,标识"我要查 A1 设备"
四种常用 HTTP 方法:动词
| 方法 | 中文意思 | 对应操作 | 典型场景 |
|---|---|---|---|
GET |
拿 | 查询 | 查设备、查工单 |
POST |
交 | 新增 | 提交一条新工单 |
PUT |
换 | 整体更新 | 修改工单全部信息 |
DELETE |
删 | 删除 | 关闭工单 |
这四个词合称 CRUD(Create 增 / Read 查 / Update 改 / Delete 删),就是一切业务系统的基本面。今天先用 GET,明天补齐其余三个。
状态码:服务器的"回话语气"
| 状态码 | 含义 | 人话 |
|---|---|---|
| 200 | OK | 办妥了 |
| 201 | Created | 新建成功 |
| 400 | Bad Request | 你发的东西有问题 |
| 404 | Not Found | 你要的东西不存在 |
| 500 | Internal Server Error | 服务器自己炸了 |
懂的同学这段可以直接往下翻。不过 404 和 500 的区别(一个是你请求错了,一个是服务器内部错)后面调试天天用,不放心十秒扫一遍也行。
🛠️ 安装与第一个服务
第 1 步:建虚拟环境装库
# 新建项目文件夹并进入
mkdir fastapi_demo
cd fastapi_demo
python -m venv venv
venv\Scripts\activate
# fastapi 是框架,uvicorn 是"服务器"(负责真正监听端口、收发网络请求)
pip install fastapi "uvicorn[standard]"
💡 两个东西分工不同:FastAPI 负责"请求来了调用哪个函数",uvicorn 负责"网络收发"。FastAPI 应用要靠 uvicorn 跑起来。
第 2 步:写第一个应用
新建 main.py:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def root():
return {"message": "FDE 设备服务已启动", "status": "ok"}
逐行拆解:
app = FastAPI()
# 创建一个应用实例,相当于"开了一家餐厅"
@app.get("/")
# 装饰器:登记规则------"有人用 GET 访问首页 /,就调用下面这个函数"
def root():
return {...}
# 返回字典 → FastAPI 自动把它转成 JSON 发回去(上周学的 json 它帮你干了)
那个
@app.get(...)叫装饰器 ,长着 @ 符号。现在不用研究它的原理,记住这个套路即可:函数上面贴一个 @app 路由标签,这个函数就变成了网络接口。
第 3 步:启动服务
uvicorn main:app --reload
main:app 的意思:main.py 文件里那个叫 app 的对象。--reload 是开发神器------你改完代码保存,服务自动重启,不用手动管。
看到这样的输出就是成功了:
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Application startup complete.
第 4 步:访问它
打开浏览器,地址栏输入 http://localhost:8000/,你会看到:
{"message": "FDE 设备服务已启动", "status": "ok"}
🎉 你的第一个 API 服务跑起来了! 此刻你的电脑既是客户端又是服务器。按 Ctrl + C 可以停掉服务。
📖 自动文档:FastAPI 白送的杀手锏
访问 http://localhost:8000/docs:
一个完整的接口测试页面(Swagger UI)自动出现了------你没写一个字的文档!
/docs → Swagger UI(可交互文档,能直接在页面上点"Try it out"测接口)
/redoc → ReDoc(另一种阅读型文档样式)
在 /docs 页面你可以:
-
点开
GET /接口 -
点 Try it out → Execute
-
直接看到真实响应、状态码、响应头
📌 FDE 交付时,客户的开发同事问"你这接口怎么调?"------你把
/docs链接发过去就完事了。自动生成的实时文档是 FastAPI 淘汰老一代框架的重要理由,明天你会更深地体会到。
🔧 路径参数:把信息放在网址里
新建一个接口,查指定设备的分级结果(复用上周的业务函数):
from fastapi import FastAPI
app = FastAPI()
def grade_temperature(t):
if t >= 90:
return "紧急"
elif t >= 80:
return "严重"
elif t >= 70:
return "注意"
return "正常"
@app.get("/grade/{temperature}")
def get_grade(temperature: int):
level = grade_temperature(temperature)
return {"temperature": temperature, "level": level}
注意花括号 {temperature}:它是网址里的占位符,用户填什么,函数就收到什么。
访问试一下:
http://localhost:8000/grade/85 → {"temperature": 85, "level": "严重"}
http://localhost:8000/grade/60 → {"temperature": 60, "level": "正常"}
类型注解自动校验(第一次尝到甜头)
注意参数写的是 temperature: int。这个 : int 叫类型注解。FastAPI 会拿它做自动校验:
访问 /grade/85 → 85 能转成 int → 正常
访问 /grade/abc → abc 转不成 int → FastAPI 自动返回 422 错误:
{
"detail": [{
"type": "int_parsing",
"loc": ["path", "temperature"],
"msg": "Input should be a valid integer"
}]
}
你一行校验代码都没写,非法输入被干净利落地挡在门外,错误信息还特别规范。这就是 FastAPI 的核心爽点之一。
多个路径参数
@app.get("/devices/{device_id}/sensors/{sensor_type}")
def read_sensor(device_id: str, sensor_type: str):
return {"device": device_id, "sensor": sensor_type}
访问 /devices/A1/sensors/temperature → 两个值都能收到。
🔍 查询参数:问号后面的筛选条件
路径参数适合"定位资源",查询参数适合"筛选/分页/可选条件"。长这样:
/devices?status=running&limit=10
└──────┬───────┘ └────┬────┘
第一个条件 再追加条件用 & 连接
在 FastAPI 里,函数里那些没在路径中出现的参数,自动变成查询参数:
DEVICES = [
{"id": "A1", "temperature": 65, "running": True},
{"id": "A2", "temperature": 82, "running": True},
{"id": "A3", "temperature": 91, "running": True},
{"id": "B1", "temperature": 75, "running": False},
]
@app.get("/devices")
def list_devices(running: bool | None = None, limit: int = 100):
result = DEVICES
# 传了 running 就筛选,没传就返回全部
if running is not None:
result = [d for d in result if d["running"] == running]
return {"count": len(result[:limit]), "data": result[:limit]}
注:
bool | None表示"布尔值或者 None",是 Python 3.10+ 的写法;老版本写作Optional[bool](Day 30 细讲类型注解)。
测试:
http://localhost:8000/devices → 全部 4 台
http://localhost:8000/devices?running=true → 只看运行中的 3 台
http://localhost:8000/devices?running=true&limit=2 → 运行中的前 2 台
http://localhost:8000/devices?limit=2 → 全部数据的前 2 台
路径参数 vs 查询参数怎么选
| 场景 | 用法 | 例子 |
|---|---|---|
| 定位"哪个资源"(必填) | 路径参数 | /devices/A1 |
| 筛选/分页/排序(可选) | 查询参数 | /devices?running=true&limit=10 |
| 层级从属关系 | 路径参数 | /devices/A1/orders/3 |
实在弄不懂也没关系,用多了自然有感觉。记个经验法则:"是谁"进路径,"怎么过滤"进问号。
🛠️ FDE 实战:设备查询服务(GET 全家桶)
把 main.py 补完整:
from fastapi import FastAPI, HTTPException
app = FastAPI(title="FDE 设备管理 API", version="0.1.0")
DEVICES = [
{"id": "A1", "name": "注塑机A1", "temperature": 65, "vibration": 8,
"running": True, "owner": "李工"},
{"id": "A2", "name": "注塑机A2", "temperature": 82, "vibration": 12,
"running": True, "owner": "王工"},
{"id": "A3", "name": "注塑机A3", "temperature": 91, "vibration": 16,
"running": True, "owner": "赵工"},
{"id": "B1", "name": "冲压机B1", "temperature": 75, "vibration": 9,
"running": False, "owner": "李工"},
]
def grade(t):
if t >= 90:
return "紧急"
if t >= 80:
return "严重"
if t >= 70:
return "注意"
return "正常"
@app.get("/", tags=["基础"])
def root():
return {"service": "FDE 设备管理 API", "docs": "/docs"}
# 1. 查询单台设备(路径参数 + 404 处理)
@app.get("/devices/{device_id}", tags=["设备"])
def get_device(device_id: str):
for d in DEVICES:
if d["id"] == device_id:
return {**d, "level": grade(d["temperature"])}
raise HTTPException(status_code=404, detail=f"设备 {device_id} 不存在")
# 2. 设备列表 + 多条件筛选(查询参数)
@app.get("/devices", tags=["设备"])
def list_devices(running: bool | None = None,
level: str | None = None,
owner: str | None = None):
result = []
for d in DEVICES:
if running is not None and d["running"] != running:
continue
if level and grade(d["temperature"]) != level:
continue
if owner and d["owner"] != owner:
continue
result.append({**d, "level": grade(d["temperature"])})
return {"count": len(result), "items": result}
# 3. 实时分级计算(路径参数直接传温度)
@app.get("/grade/{temperature}", tags=["工具"])
def calc_grade(temperature: float):
return {"temperature": temperature, "level": grade(temperature)}
验收步骤
-
uvicorn main:app --reload启动 -
打开
/docs,观察三个接口都已自动列好、还按tags分了组 -
逐个 Try it out:
-
GET /devices/A3→ 返回带 level 的完整档案 -
GET /devices/A9→ 返回规范的 404 -
GET /devices?level=严重→ 返回 A2 -
GET /devices?running=true&owner=李工→ 只返回 A1 -
GET /grade/87.5→ 注意 float 类型,小数也能收
-
关于 404:HTTPException
raise HTTPException(status_code=404, detail="设备不存在")
业务上查不到东西时,不能返回 200 再塞个错误信息------那叫"骗客户端"。正确姿势是抛出 HTTPException,FastAPI 会把它变成标准 HTTP 错误响应。状态码本身就是接口契约的一部分。
💡 现在数据还存在内存列表里(服务重启数据就没了)。别着急,这是为了专注学接口本身。下周 SQL 模块接上 MySQL,数据就能持久化;接口代码几乎不用动------分层的好处提前感受一下。
📝 本课小结
| 知识点 | 一句话记住 |
|---|---|
| API 服务 | 一直运行、等别人通过 HTTP 调用函数的程序 |
| HTTP 四方法 | GET 查 / POST 增 / PUT 改 / DELETE 删 |
| 状态码 | 200 成功 / 404 没有 / 422 参数错 / 500 服务器炸 |
| FastAPI | 定义函数 + 贴 @app.get 标签 = 接口 |
| uvicorn | 真正监听端口的服务器:uvicorn main:app --reload |
| 自动文档 | /docs 白送可交互接口文档 |
| 路径参数 | /devices/{id},定位"是谁",必填 |
| 查询参数 | ?running=true&limit=10,筛选条件,可选 |
| 类型注解校验 | id: int 非法输入自动返回 422 |
| HTTPException | 业务错误用标准状态码回应,如 404 |
💡 今天最核心的认知 :API 是 FDE 把 AI 能力嵌入客户系统的标准插座。你写的分级函数一旦挂上 HTTP 接口,客户的工单系统、MES、甚至一个 AI Agent 都能通过标准方式调用它------编程语言无关、系统无关。这就是"服务化"的价值。
📋 课后练习
-
健康检查接口 :新增
GET /health,返回当前时间(用 datetime)和服务状态{"status": "healthy", "time": "..."}。这是运维监控最爱调的接口。 -
搜索接口 :新增
GET /search?q=关键字,在设备名称里模糊匹配(提示:q in d["name"]),支持可选的min_temp参数,只返回温度高于该值的设备。在/docs里测试三组组合。 -
故意触发错误 :不写代码,只用浏览器访问,分别制造一次 404(查不存在的设备)和一次 422(给
/grade/温度传文字),把两种返回的 JSON 抄下来对比,理解它们各自在告诉调用方什么。
💭 今日反思
从"自己跑脚本"到"把能力挂上网等别人调",这个转变让你想到实施工作里的哪种升级?(现场工具 → 标准化服务?)
为什么说"自动文档"对 FDE 特别值钱?想想你交付项目时和客户 IT 人员对接的痛苦经历。
明天预告 :今天只做了"查"。明天上 POST/PUT/DELETE 完整增删改查,并学习 Pydantic 模型------用一个类定义请求体长什么样,FastAPI 自动完成校验、序列化和文档。学完明天,你将拥有一个完整的工单管理 API,这是第 6 周对接企业系统的预演。
FDE 学习系列教程 · 第二阶段 · 第 2 周 Day 3 · 完