FastAPI入门:Python后端开发新手指南
一个准备考公上岸的在职程序员的碎碎念
上周五晚上,我正盯着公司那个 Java 写的老掉牙运营后台发呆——页面卡得像在用2G网,接口返回动不动就是 500 Internal Server Error。产品经理又来催新功能了:“能不能加个实时数据看板?下周上线。”我默默看了眼日历:距离我报名的省考只剩47天。
那一刻,我突然意识到:与其在这破系统里修修补补,不如自己搞个轻量级的替代方案。于是,FastAPI 进入了我的视野。
被“逼”学 FastAPI 的前因后果
我在这家公司干了三年多,写 Java 写到看见 Spring Boot 的 logo 就反胃。团队里清一色 Java 技术栈,连个简单的运营工具都要走完整的微服务流程:注册中心、配置中心、网关、熔断……就为了查个用户列表,调三个服务,等五秒加载。运维大哥还美其名曰:“高可用架构。”
但现实是:我们80%的内部工具根本不需要这么重。尤其是运营部门提的需求,今天要导出报表,明天要批量改状态,后天又要对接第三方 API——全是短平快的小活儿。用 Java 做?光 Maven 依赖就能把我送走。
去年双11期间,我们线上出了个 P0 级 Bug:因为某个异步任务没处理好,导致几千条订单状态异常。我当时连夜排查,发现罪魁祸首是一个用 Java 写的“简单”回调服务——代码臃肿、日志混乱、单元测试为零。修完 Bug 那天早上,我对着咖啡机发誓:下次再做这类项目,死也不用 Java。
于是,FastAPI 成了我的新宠。
为什么是 FastAPI?不是 Flask?不是 Django?
说实话,一开始我也考虑过 Flask。毕竟轻量、灵活,社区也大。但当我翻到 FastAPI 的文档时,眼睛直接亮了:
- 自动 Swagger UI:不用手写 API 文档,自动生成,还能在线调试
- Pydantic 数据校验:请求参数自动验证,再也不怕前端传个字符串进来当 int 用
- 异步支持原生:async/await 直接上,性能杠杠的
- 类型提示友好:作为一个被 Java 的泛型折磨过的人,我对类型安全有执念
最关键的是——它快。官方 benchmark 显示,FastAPI 的性能接近 Node.js 和 Go,远超 Flask 和 Django。对于我们这种偶尔要处理几千条数据导出的运营接口来说,速度就是生命线。
实战:三天撸一个运营小工具
目标很明确:给运营同事做一个“用户行为日志查询工具”。需求很简单:
- 按日期范围筛选
- 按用户 ID 或设备 ID 查询
- 导出 CSV
第一天:搭架子 + 定义模型
from fastapi import FastAPI
from pydantic import BaseModel
from datetime import date
app = FastAPI(title="运营日志查询工具", version="0.1.0")
class LogQuery(BaseModel):
start_date: date
end_date: date
user_id: str | None = None
device_id: str | None = None
@app.post("/logs/query")
async def query_logs(query: LogQuery):
# 后续接数据库查询
return {"message": "ok"}
跑起来,打开 http://localhost:8000/docs —— 哇!Swagger UI 自动出来了,连请求体示例都给你生成好了。运营同事看了直呼“这比我们现在的 Java 后台高级多了”。
第二天:接数据库 + 性能优化
我们用的是 PostgreSQL,配合 SQLAlchemy Core(不是 ORM,Core 更快更可控)。这里踩了个坑:默认同步查询会阻塞整个事件循环。
刚开始我是这么写的:
def get_logs_from_db(query: LogQuery):
# 同步查询
return conn.execute(select(...)).fetchall()
结果一压测,QPS 直接掉到 20。后来改成用 databases 库做异步查询:
import databases
database = databases.Database("postgresql+asyncpg://...")
@app.on_event("startup")
async def startup():
await database.connect()
@app.on_event("shutdown")
async def shutdown():
await database.disconnect()
@app.post("/logs/query")
async def query_logs(query: LogQuery):
# 异步查询
rows = await database.fetch_all(query=...)
return rows
QPS 直接飙到 800+。爽!
第三天:加权限 + 部署
公司要求所有内部工具都要走统一认证。FastAPI 的依赖注入系统太香了:
from fastapi import Depends, HTTPException
async def verify_token(token: str = Header(...)):
if not validate_token(token): # 调公司 auth 服务
raise HTTPException(status_code=401, detail="Unauthorized")
return True
@app.post("/logs/query")
async def query_logs(
query: LogQuery,
_: bool = Depends(verify_token)
):
...
部署用 Docker + Gunicorn + Uvicorn worker:
FROM python:3.10-slim
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
CMD ["gunicorn", "-k", "uvicorn.workers.UvicornWorker", "main:app"]
Nginx 反向代理一配,HTTPS 一开,上线!整个过程不到三天,而如果用 Java,光搭框架就得一周。
性能对比:FastAPI vs 我们的 Java 服务
为了说服团队,我做了个简单对比(同样是查询 1000 条日志记录):
| 指标 | FastAPI (async) | 公司 Java 服务 |
|---|---|---|
| 平均响应时间 | 120ms | 2.1s |
| 内存占用 | 80MB | 650MB |
| 启动时间 | 1.2s | 18s |
| 代码行数 | 120 行 | 450 行 |
看到这个数据,连一向保守的后端组长都说:“要不以后小工具都用 FastAPI?”
踩过的坑 & 经验总结
- 不要滥用 async:如果你的数据库驱动不支持异步(比如 MySQL 的 aiomysql 很弱),强行 async 反而更慢。PostgreSQL + asyncpg 是黄金组合。
- Pydantic 模型别嵌套太深:我们有个接口返回三层嵌套对象,序列化耗时占了 40%。后来改成分页 + 扁平结构,性能提升明显。
- 生产环境记得关 debug:
app = FastAPI(debug=False),不然报错信息会暴露服务器路径。 - 日志别打太多:FastAPI 默认不集成日志,建议用
structlog或直接logging,按 trace_id 打印,方便排查。
写在最后:考公人也能搞技术
很多人觉得“准备考公就别折腾技术了”,但我反而觉得——越是想跳出当前环境,越要保持技术敏感度。FastAPI 让我意识到:后端开发不一定要被厚重的框架绑架。轻量、高效、开发者体验好,才是王道。
而且,GitHub 上 FastAPI 的 star 数已经突破 60k(截至 2024 年中),社区活跃,生态完善。无论是做个人项目、副业,还是跳槽面试,都是加分项。
上周我把这个工具开源到了 GitHub([假装有链接]),README 里写了句:“献给所有被 Java 微服务折磨的运营工具开发者。”没想到居然有 30 多个 star,还有人提 PR 优化了 CSV 导出逻辑——这种正反馈,比加班改 Bug 快乐多了。
所以,如果你也在用 Java 写一些“本不该那么重”的服务,不妨试试 FastAPI。说不定哪天,你也能一边刷行测题,一边优雅地交付需求。
毕竟,程序员的终极自由,不是 996,而是——我想用什么技术,就用什么技术。
P.S. 本文所有代码已在公司内网 GitLab 归档,但为了避嫌,GitHub 上放的是脱敏版。考公人也要注意信息安全啊!

评论 0