小白python入门 - 40. Web 服务与 FastAPI 入门
2026/7/27 6:46:40 网站建设 项目流程

1. 本课定位:是什么、为何重要

上一阶段你已经会当「客户端」:用 requests / httpx 去调别人的 HTTP 接口,会看状态码、会设超时、会读 JSON。那套能力解决的是「我去找别人拿数据」。可是真实后端岗位的核心产出,往往是反过来的——别人(浏览器、App、别的服务)来找你拿数据。如果只会写「跑完就退出」的脚本,就没法把业务能力变成可联调、可部署的接口。

所以本课先完成角色切换:你要启动一个常驻进程,监听本机端口,接收请求,返回 JSON。技术栈选 FastAPI + Uvicorn:前者用函数和类型注解声明路由,后者负责真正监听端口并调用你的应用。学完你应能本地起服务、用浏览器 /docs 或 curl 验证,并为后续书签 API 主线打底。

阶段 B 你是客户端;本阶段起你是服务端

概念一句话
Web 服务 / API用 HTTP 把业务能力暴露给浏览器、App、其它程序
FastAPI用 Python 函数 + 类型注解声明路由;自动校验与 OpenAPI 文档
UvicornASGI 服务器:监听端口,把网络字节流变成「调用你的 app」
ASGI异步网关接口约定;知道「炉灶与菜谱之间有标准」即可

为何重要:不会起服务,就无法把路由、模型、数据库、鉴权串成产品。

对比已学:

已学(阶段 B)本课(阶段 C)
发出请求、解析响应接收请求、构造响应
关心对方 URL/状态码自己决定路径、状态码、Body
超时、重试在客户端进程要常驻、端口要监听
调外部演示站别人(或未来的你)来调你

生活类比:

角色像什么
客户端脚本你去餐厅点菜、等上菜
Web 服务你开餐厅:听点单、出菜、报状态
FastAPI菜单与出菜流程(路由逻辑)
Uvicorn店面开门营业(进程监听)

贯穿业务:书签 API(本课先健康检查与问候;后续课逐步加路由、模型、配置、落库)。


2. 本质:一次 HTTP 交换里你站哪边

很多人一听「写后端」就想到 Socket、多线程、协议细节,结果迟迟不敢动手。其实入门阶段你要抓住的本质很简单:一次 HTTP 交换里,你的进程站在服务器一侧——读方法/路径/头/体,写状态码/头/体。框架已经把监听和协议解析包好了,你主要写「路径对应哪个函数、返回什么 JSON」。

上一节把角色切换说清了,这一节用一张请求往返图和三层分工表,把「菜谱 / 炉灶 / 接口约定」钉牢。地图清楚后,最小应用代码才不会变成照抄咒语。

浏览器 / 脚本 / 前端 你的 Uvicorn + FastAPI | ---- GET /health ----> | | <--- 200 {"status":"ok"} |
像什么本课角色
FastAPI 应用菜谱(路径与逻辑)你写的app
Uvicorn炉灶(跑起来)命令行启动
ASGI炉灶与菜谱的接口约定知道有即可

本质一句话:服务端 = 常驻进程 + 路由函数 + HTTP 响应。


3. 约束与常见坑

理解了「站在服务端」之后,必须立刻补边界:进程要一直跑、端口会冲突、本机地址不等于公网可达、改代码不生效通常是没热重载或改错文件。这些坑在课堂演示里几乎必现,先列出来能省半小时抓狂。

这一节用清单和对照表把红线画清。目的不是吓人,而是让你第一次uvicorn失败时知道该查哪一类问题,而不是怀疑「FastAPI 是不是坏了」。

约束:

  1. 进程要一直跑着,关掉终端服务就停(与「跑完就退出」的脚本不同)。
  2. 端口只能被一个进程占用;冲突就换端口。
  3. 默认只给本机访问127.0.0.1)更安全;绑定0.0.0.0才对外网卡开放。
  4. 开发用--reload,生产不要依赖热重载当部署方案。
  5. 返回的dict会变成 JSON;不能直接返回任意不可序列化对象(裸datetime等需配置或转换)。

常见坑:

现象正确直觉
把 FastAPI 当「还要自己写 socket」无从下手框架已封装监听,你写路由函数即可
改代码不生效仍是旧逻辑--reload,或确认改的是正在运行的文件
Address already in use起不来--port或关掉占用进程
只开了服务、不去请求「没反应」用浏览器/curl//docs主动访问
外网朋友访问不了本机127.0.0.1连不上本地开发本就如此;部署是后面的课
main:app写成文件名乱猜导入失败模块路径 + 变量名app

4. 最小应用:定义与创建

坑讲完,开始动手认最小闭环:创建FastAPI实例、用装饰器挂 GET 路由、返回 dict。这三步对应「有应用、有路径、有响应」。

你会看到装饰器在导入模块时就完成路由注册——不是「调用函数时才注册」。理解这一点,后面拆文件、include_router时才不会疑惑「为什么 import 一下路由就生效了」。

fromfastapiimportFastAPI app=FastAPI(title="Bookmark API",version="0.1.0")@app.get("/")defroot():return{"message":"hello bookmark api"}@app.get("/health")defhealth():return{"status":"ok"}
写法含义
app = FastAPI(...)创建应用实例(Uvicorn 要加载它)
@app.get("/health")注册GET/health
return dict自动 JSON 序列化,默认状态码200

关键语义:装饰器在导入模块时完成路由注册。

预期输出形态(访问/health):

{"status":"ok"}

5. 运行方式对照

写好app还不等于服务在跑——还需要 Uvicorn 加载它。main:app这种写法初学者常读错:左边是模块,右边是变量名,中间冒号不是文件扩展名。

这一节把开发命令、包路径写法、文档入口放进对照表,并说明/docs/redoc/openapi.json各自干什么。你会发现:框架根据路由自动生成 OpenAPI,文档页只是它的可视化。

方式命令直觉何时用
开发uvicorn main:app --reload --host 127.0.0.1 --port 8000本课默认
指定模块路径uvicorn app.main:app包结构项目
生产倾向多进程/容器 + 无 reload(后续部署课)上线

main:app读作:模块main里的变量app

文档入口用途
/docsSwagger UI,可点按钮试调
/redoc更偏阅读的文档页
/openapi.json机器可读契约(后续课展开)
参数含义
--reload代码变更自动重启(仅开发)
--host 127.0.0.1只监听本机回环
--port 8000端口号;冲突则改

6. 小步示例:查询参数预览

严格的 Query 系统化在下一课,但本课若完全不碰「带参数的接口」,体验会偏干。这里用最小/hello?name=让你看见:函数参数可以来自查询串,FastAPI 会帮你填。

把它当作预告,不要求一次吃透校验与 422。重点是:服务端同样在「约定 URL 形状」,客户端拼?name=alice就能对上。

@app.get("/hello")defhello(name:str="world"):return{"greeting":f"hello,{name}"}
请求响应要点
GET /hello{"greeting":"hello, world"}
GET /hello?name=alice{"greeting":"hello, alice"}

7. 落地场景:书签服务从哪起步

贯穿业务是书签 API,但第一课不必上 CRUD。先定「服务活着」和「能问候」两个最小能力,运维探活与前端联调都用得上。

这一节用表格把场景和接口直觉对齐,避免一上来就设计大而全的资源树。正确节奏是:先能起、能验、能改代码热更新,再加资源路径。

场景最小接口直觉
运维探活GET /health{"status":"ok"}
给前端的问候GET /hello?name=alice
书签服务雏形本课先健康检查;第 41 课起加资源路径
自测文档打开/docs,Try it out

8. 修改前 / 修改后:客户端思维 vs 服务端思维

学过 requests 的人容易把「写服务」也想成「我再发一次请求」——方向反了。用对照表把思维拧过来:你不再拼对方 URL,而是定义自己的路径;不再解析对方 JSON,而是构造自己的 JSON。

这种对照会反复出现在后面几课:路径参数、请求体、依赖注入,都是在服务端兑现「对外约定」。

维度修改前(客户端)修改后(服务端)
主动方你发起别人发起,你响应
进程短命脚本常驻监听
成功标志对方 200你返回 200 与约定字段
调试入口打日志看响应/docs+ curl 双验证
失败常见超时、DNS端口占用、路由未注册

9. 环境与目录建议

工具链没摆好,后面所有课都会卡在「包找不到 / 命令不对」。这一节固定:虚拟环境、依赖版本下限、Windows 下如何跑cat <<'EOF'类脚本。

Windows 用户推荐 Cygwin 或 WSL 执行带 heredoc 的 bash 片段;PowerShell 也可手建文件,但课程示例统一按 bash 写法给出,便于复制。

项目要求
Python3.10+(推荐 3.12)
fastapiuvicorn[standard]
Windows推荐 Cygwin / WSLcat <<'EOF'脚本;或 VS Code 终端手建文件
mkdir-p~/python-lab/src/day40cd~/python-lab/src/day40 python3-mvenv .venvsource.venv/bin/activate# Windows PowerShell: .\.venv\Scripts\Activate.ps1pipinstall'fastapi>=0.110''uvicorn[standard]>=0.27'

10. 综合实践:完整可运行脚本

前面是分块概念,这一节一次落地:写入main.py、启动 Uvicorn、另开终端验证。请完整跑通,不要只看不敲——「服务起来了」的体感建立不起来,后面路由课会虚。

Windows 请在 Cygwin/WSL 中执行 heredoc;若必须用 PowerShell,可手动创建同名文件并粘贴 EOF 之间的内容。服务占用前台终端时,验证命令请开第二个终端。

mkdir-p~/python-lab/src/day40cd~/python-lab/src/day40# 已激活 venv 并安装依赖后:cat>main.py<<'EOF' from fastapi import FastAPI app = FastAPI(title="Day40 Bookmark API", version="0.1.0") @app.get("/") def root(): return {"message": "hello bookmark api", "course": 40} @app.get("/health") def health(): return {"status": "ok"} @app.get("/hello") def hello(name: str = "world"): return {"greeting": f"hello, {name}"} EOFuvicorn main:app--reload--host127.0.0.1--port8000

另开终端验证:

curl-shttp://127.0.0.1:8000/healthcurl-s"http://127.0.0.1:8000/hello?name=alice"curl-shttp://127.0.0.1:8000/

浏览器打开:http://127.0.0.1:8000/docs→ 选接口 →Try it outExecute

预期输出:

{"status":"ok"} {"greeting":"hello, alice"} {"message":"hello bookmark api","course":40}
检查项通过标准
健康检查Body 含"status":"ok"
问候name进入 greeting
文档/docs能看到三条 GET
热重载message字符串后刷新仍更新(保存后等一秒)

11. 常见问答

课堂高频问题集中在:FastAPI 和 Flask 差在哪、Uvicorn 能不能省略、为什么必须另开终端、main:app报错怎么办。集中答疑,减少「概念都懂了但命令跑不通」的挫败感。

Q:FastAPI 和 Flask 入门差在哪?
A:FastAPI 强调类型注解、自动校验与 OpenAPI;本系列统一 FastAPI,不强制对比深度。

Q:能不用 Uvicorn 吗?
A:开发期几乎总要 ASGI 服务器;Uvicorn 是官方推荐默认之一。

Q:为什么 curl 要另开终端?
A:前台跑着的 Uvicorn 占住了当前 shell;不停服务就另开窗口发请求。

Q:Could not import module "main"
A:当前目录是否有main.py;是否在项目目录执行;包结构时用app.main:app

Q:返回中文乱码?
A:终端编码与 JSON 本身 UTF-8;浏览器/docs一般正常。确保源文件 UTF-8 保存。


12. 错误示范对照

专辟对照,把「假服务端」和「真最小服务」并排看。常见错误包括:写了函数却没装饰器、return 了不可序列化对象、host/port 乱绑导致自己都访问不了。

错误写法问题正确直觉
定义了def health()无装饰器路由未注册@app.get("/health")
return open("x")无法 JSON 化返回 dict/list/模型
print不 return客户端拿到 null/空明确 return 响应体
绑定错误端口却 curl 8000连接失败命令与 curl 端口一致
# 修改前:有函数,无路由defhealth():return{"status":"ok"}# 修改后:@app.get("/health")defhealth():return{"status":"ok"}

13. 自我检查清单

学完先别急着翻第 41 课。用清单打勾:角色切换、三层分工、最小代码、启动命令、curl 与 /docs 双验证。勾不上的回到对应小节五分钟,比往前赶更有效。

  • 能用一句话说清客户端 vs 服务端
  • 能说出 FastAPI 与 Uvicorn 各干什么
  • 会写GET /GET /health
  • uvicorn main:app --reload并成功访问
  • 会用/docsTry it out
  • 会用 curl 验证 JSON
  • 知道端口占用时如何处理

14. 与后续课的衔接(地图)

本课只搭舞台。后面书签 API 会按「路径 → 请求体 → 依赖配置 → 数据库」加厚。知道地图,才不会觉得每课在换题材。

你将加上
41路径/查询参数、状态码、APIRouter、内存书签读删
42Pydantic 模型、POST/PATCH Body
43Depends、Settings、.env
44SQLAlchemy + SQLite 持久化 CRUD

15. 客户端调自己的服务(闭环)

阶段 B 你会用 requests 调别人;现在服务在本机,完全可以用同一套客户端能力调自己,形成「一端写服务、一端写调用」的闭环。这对以后写集成测试、健康检查脚本也很有用。

服务仍要用 Uvicorn 先跑着;下面脚本在另一个终端执行。超时建议带上,避免服务没起时一直挂起。

importrequests base="http://127.0.0.1:8000"r=requests.get(f"{base}/health",timeout=5)print(r.status_code,r.json())r2=requests.get(f"{base}/hello",params={"name":"lab"},timeout=5)print(r2.json())

预期输出形态:

200 {'status': 'ok'} {'greeting': 'hello, lab'}
方式适合
浏览器/docs探索、演示
curl终端快速验
requests/httpx脚本化、后续测试

总结

到了收束的时候。若整课只能带走几句:角色已从「调别人」换成「被别人调」;FastAPI 写 app,Uvicorn 跑 app;dict 变 JSON;用 /docs 和 curl 双验证;进程常驻、端口唯一、本机开发先绑回环地址。

这些句子后面每课都会用到。先保证「能起、能调、能改」,再谈漂亮架构。

  • 服务端 = 常驻进程 + 路由函数 + HTTP 响应。
  • FastAPI 声明路由与文档;Uvicorn 负责监听与调用 app。
  • main:app= 模块里的应用实例;开发加--reload
  • return dict→ JSON,默认 200;用/docs与 curl 验证。
  • 端口冲突换端口;本地127.0.0.1不等于公网可达。
  • 贯穿业务从书签 API 健康检查起步,后续课逐步加厚。

小练笔

练习用来自测,不要求一次全对,更不要先翻答案。题型覆盖选择、判断、简答与可选实践:建议你真的改一行返回字段,保存后看热重载是否生效。

做题时优先用自己的话解释「为什么」。卡很久的题,回到「三层分工」和「运行方式」两节通常就能想通。

题 1

Uvicorn 的主要职责?

A. 写 SQL
B. ASGI 服务器监听并调用 app
C. 画前端页面

题 2

uvicorn main:app里的app指什么?

题 3

判断:浏览器打开/docs能试调接口,说明 OpenAPI 文档由框架根据路由自动生成。

题 4

端口被占用时,优先做什么?

题 5

用「方法、URL、期望状态码、请求体、响应体」描述一次对/health的成功访问。

题 6

判断:开发环境绑定127.0.0.1后,公网用户一定能访问你的服务。

题 7

为什么服务启动后当前终端不能再直接敲很多交互命令?

题 8

GET /hello?name=bob若路由是def hello(name: str = "world"),响应 greeting 应是什么?

题 9(可选实践)

/增加字段"domain": "bookmark",保存后不手动重启(依赖--reload),curl 验证新字段出现。

题 10

一句话区分 FastAPI 与 Uvicorn。


小练笔参考答案

参考答案在下面。请先自己做完再看。答案只给标准方向,简答题意思对即可。

若你的表述和答案不同但道理成立,可以算对。真正要修正的,是把客户端/服务端角色搞反,或以为框架还要你手写 socket 的理解。

题 1

B

题 2

main模块中FastAPI()创建的应用实例变量。

题 3

题 4

换端口或结束占用该端口的进程。

题 5

示例:GEThttp://127.0.0.1:8000/health;无 Body;期望 200;Body{"status":"ok"}

题 6

题 7

Uvicorn 前台占用该终端;验证请另开终端,或后台运行(开发期另开更直观)。

题 8

hello, bob(即{"greeting":"hello, bob"})。

题 9

以你机器为准;保存后 curl/应出现"domain":"bookmark"

题 10

FastAPI 写应用与路由;Uvicorn 跑 ASGI 应用并监听端口。(合理即可)

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询