1020 字
约 3 分钟
7
S10-B05 · Flask 路由与错误页
适用读者:要写一个小服务、或要接手 Flask 老项目的人。
前置:S10-B03。
实测环境:Flask 3.1.3 / Python 3.12.3(2026-11-05 真实启动 + curl)。
覆盖旧文:A-1495(Flask 路由注册,38 点)、A-1496(404/500 错误页,32 点)= 70 点。
覆盖扩展:E-S10-007(errorhandler与abort)。
上一篇:S10-B04 · FastAPI 入门:类型即文档
下一篇:S10-J01 · 依赖治理。
1. 一句话结论
Flask 是"微框架":给你路由和请求上下文,其余(校验、文档、异步)都要自己接。灵活,但一致性靠团队纪律。
| 能力 | Flask | FastAPI(对照) |
|---|---|---|
| 路由 | @app.route |
@app.get/post |
| 参数校验 | 手写 / 第三方(pydantic 可接) | 内建(422 明细) |
| 文档 | 需扩展(flask-smorest 等) | 内建 /docs |
| 异步 | 3.x 支持,但生态多为同步 | 原生 async def |
| 学习曲线 | 最低 | 低(但要懂类型标注) |
2. 实测:路由注册
from flask import Flask, jsonify, abort
app = Flask(__name__)
@app.route("/items/<int:item_id>")
def item(item_id):
if item_id > 100:
abort(404) # 抛 404,交给 errorhandler
return jsonify(id=item_id, name="apple")
路由的三件事:
| 要素 | 说明 |
|---|---|
@app.route(path) |
注册路径;<int:item_id> 是转换器(类型转换 + 匹配约束) |
| 视图函数返回值 | 字符串(HTML)/ jsonify(JSON)/ (body, status) 元组 |
| 方法限制 | 默认只允许 GET;methods=["POST"] 显式声明 |
转换器类型:<int:>、<float:>、<path:>(含 /)、<uuid:>、默认 <string>(不含 /)。
2.1 实测响应
$ curl -s http://127.0.0.1:19061/items/5
{"id":5,"name":"apple"}
3. 自定义错误页(E-S10-007)
@app.errorhandler(404)
def nf(e):
return jsonify(error="not found"), 404
@app.errorhandler(500)
def se(e):
return jsonify(error="internal"), 500
@app.route("/boom")
def boom():
raise RuntimeError("人为异常")
实测:
$ curl -s -w " [HTTP %{http_code}]" http://127.0.0.1:19061/items/200
{"error":"not found"} [HTTP 404]
$ curl -s -w " [HTTP %{http_code}]" http://127.0.0.1:19061/boom
{"error":"internal"} [HTTP 500]
要点:
| 点 | 说明 |
|---|---|
errorhandler 是按状态码注册 |
可对 404/500/403 分别定义 |
必须返回 (body, status) |
只返回 body 会变成 200 |
abort(404) 会触发 handler |
单纯 return "x", 404 不会触发(差异容易踩) |
| 未捕获异常 → 500 | 生产环境应关闭 debug=True,否则返回调试页而非你的 JSON |
安全提醒:
app.run(debug=True)在生产会泄露源码与堆栈;部署应用 WSGI(gunicorn/uwsgi)+ 关闭 debug。
4. 与 FastAPI 的一处关键差异(实测对照)
同一个"路径参数类型不匹配"的请求:
| 请求 | Flask | FastAPI |
|---|---|---|
/items/abc |
404(转换器不匹配,路由根本没命中) | 422(路由命中,参数校验失败) |
为什么重要:
| 语义 | 含义 |
|---|---|
| Flask 的 404 | "这个 URL 不存在" —— 客户端会以为接口没了 |
| FastAPI 的 422 | "参数类型不对" —— 客户端知道是自己传错了 |
这条差异直接决定前端能不能做"参数错误提示"。迁移时(J02)要显式处理。
5. 五个易踩点
| 坑 | 说明 |
|---|---|
debug=True 上生产 |
源码泄露 + 交互式调试器可执行代码 |
只 return body 不返回 status |
状态码变 200 |
abort 与 return tuple 混用 |
后者不触发 errorhandler |
| 路由尾斜杠 | /items 与 /items/ 默认视为不同(strict_slashes) |
| 蓝图(Blueprint)忘记注册 | 路由 404,且不易发现(注册在 app.register_blueprint) |
6. 自检
<int:item_id>与<item_id>的区别是什么?abort(404)与return ..., 404都会触发errorhandler吗?- 为什么 Flask 对
/items/abc返回 404 而 FastAPI 返回 422? - 生产环境为什么必须关闭 debug?
- 蓝图未注册会有什么现象?
7. 下一篇
S10-J01 · 依赖治理:requirements / environment.yml / 锁版本
两个框架都跑通了,下一步是"让它们在别人机器上也跑通"。下一篇给出可复现的三件套:Python 版本锁定、精确版本、哈希校验。
本篇属于系列《S10 · Python 语言与环境》。旧文来源:A-1495/A-1496;扩展点 E-S10-007。Flask 3.1.3 响应为 2026-11-05 实测。
S10-B05 · Flask 路由与错误页
https://www.clxhxhhr.top/posts/5320/ 评论
0 条
还没有评论,先写一条吧。