FastAPI入门:Python后端开发新手指南
上个月底,我终于把婚礼请柬发出去了。本以为能喘口气,结果第二天产品经理就在群里@我:“下周三上线新活动接口,双11预热就靠你了!” 我默默看了眼日历——距离婚礼还有42天,而我的代码还没跑通本地。作为一名备婚中的程序媛,白天改需求、晚上调婚纱、深夜写代码,已经是常态。坐标上海,租住在公司附近,图的就是下班晚了还能溜回家补觉。最近项目里被安排用 FastAPI 搭个新服务,说是为了替代之前那个慢得像乌龟的 Flask 服务。说实话,一开始我是抗拒的——毕竟谁想在婚礼前一个月还学新框架?但看到 GitHub 上那颗绿油油的 star 数(都快 60k 了),再想想隔壁 Go 组天天吹“高并发”,我咬咬牙,还是打开了文档。
为啥是 FastAPI?不是 Flask,也不是 Go?
我们组之前一直用 Flask,简单好上手,但性能确实拉胯。去年双11期间,一个促销接口直接被打爆,运维在 Slack 里疯狂@我们:“CPU 98%!请求队列堵到明年了!” 当时我就在想,是不是该换个更现代的框架。
领导倒是提过要不要试试 Go,毕竟隔壁组用 Gin 写的服务稳如老狗。但现实很骨感:全组只有我会点 Go(还是大学选修课水平),其他人连 goroutine 是啥都搞不清。而且项目 deadline 就在眼前,重写成本太高。最后技术评审会上,CTO 一锤定音:“用 FastAPI 吧,异步支持好,自动生成 OpenAPI 文档,Python 生态你们也熟。”
行吧,至少不用从零学语法了。
五分钟跑起第一个 FastAPI 服务
FastAPI 真的超友好。装个包,写几行代码,本地就能跑:
pip install fastapi uvicorn
然后新建 main.py:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "备婚中的程序媛在此!"}
启动服务:
uvicorn main:app --reload
访问 http://localhost:8000,立马看到 JSON 响应。更爽的是,访问 http://localhost:8000/docs,自动弹出 Swagger UI —— 连文档都不用手写了!测试同学看到后直接在群里发了个“👍”,说再也不用追着我要接口文档了。
对比一下 Flask 的写法,FastAPI 用类型注解(Type Hints)直接定义请求/响应结构,代码可读性高多了。比如:
from pydantic import BaseModel
class Item(BaseModel):
name: str
price: float
is_offer: bool = None
@app.post("/items/")
def create_item(item: Item):
return {"item_name": item.name, "status": "created"}
传个 JSON 过来,自动校验字段类型,错了直接返回 422 错误,附带详细错误信息。再也不用自己写 if-else 判断参数合法性了,省下时间多试两件婚纱不香吗?
异步支持:别再阻塞我的婚礼筹备!
FastAPI 最吸引我的,是它对 异步 的原生支持。我们的新接口要调第三方支付回调,还要查用户积分、发消息队列……如果用 Flask 同步模式,一个请求卡住,整个 worker 就挂了。
而 FastAPI + async/await,轻松实现非阻塞 I/O。比如:
import asyncio
import httpx
@app.get("/payment-status/{order_id}")
async def get_payment_status(order_id: str):
async with httpx.AsyncClient() as client:
resp = await client.get(f"https://payment-api.com/status/{order_id}")
return resp.json()
这里用 httpx 发起异步 HTTP 请求,不会阻塞事件循环。实测 QPS 提升了 3 倍以上(本地压测数据,别杠)。虽然比不上 Go 的 goroutine 轻量级并发,但在 Python 生态里已经算顶配了。
不过要注意:如果你的数据库驱动不支持异步(比如老版 pymysql),那异步就白搭了。我们后来换成了 asyncpg(PostgreSQL)和 aiomysql,才真正发挥出性能优势。
数据库设计:别让 schema 毁了你的婚礼心情
新服务要用 PostgreSQL,我顺手用了 SQLAlchemy Core + Pydantic 的组合。FastAPI 官方推荐用 Tortoise ORM 或 Databases,但考虑到团队熟悉度,还是选了 SQLAlchemy。
建表时特别注意字段类型和索引。比如订单状态字段,一开始我偷懒用了 VARCHAR(20),结果线上查询慢得离谱。后来改成 ENUM('pending', 'paid', 'cancelled'),加了复合索引 (user_id, status),查询速度从 800ms 降到 15ms。
另外,FastAPI 的依赖注入系统(Dependency Injection)特别适合封装 DB Session:
from sqlalchemy.ext.asyncio import AsyncSession
async def get_db():
async with async_session() as session:
yield session
@app.get("/orders/")
async def list_orders(db: AsyncSession = Depends(get_db)):
result = await db.execute(select(Order).where(Order.user_id == current_user))
return result.scalars().all()
这样每个请求自动获取独立 session,事务管理清晰,再也不用担心连接池泄漏了(上次因为这个事故,我在婚礼策划群里回消息都心不在焉)。
生产环境踩坑实录
本地跑得好好的,一上 K8s 就翻车。分享几个血泪教训:
1. Uvicorn worker 数量别乱设
默认 uvicorn main:app 只起一个进程。生产环境必须用 Gunicorn + Uvicorn workers:
gunicorn -k uvicorn.workers.UvicornWorker main:app -w 4
worker 数量建议设为 CPU 核数,别贪多。我们一开始设了 16,结果上下文切换开销太大,吞吐量反而下降。
2. 静态文件别用 FastAPI 托管
FastAPI 不是 Nginx!静态资源(比如婚礼邀请函的图片)一定要交给 CDN 或 N nginx 处理。否则高并发下内存直接爆掉。
3. 日志格式统一
记得配置结构化日志,方便 ELK 收集:
import logging
logging.basicConfig(
format='{"time":"%(asctime)s", "level":"%(levelname)s", "message":"%(message)s"}'
)
不然半夜告警,你看着满屏 unstructured log,真的想砸电脑。
和 Go 对比:FastAPI 真的够用吗?
我知道肯定有人问:“为什么不直接上 Go?” 实话实说,Go 在性能、内存占用、编译部署上确实碾压 Python。但我们评估后发现:
| 维度 | FastAPI (Python) | Go (Gin) |
|---|---|---|
| 开发速度 | ⭐⭐⭐⭐⭐(类型安全+生态) | ⭐⭐⭐(需要手动写很多) |
| 性能 | ⭐⭐⭐(异步够用) | ⭐⭐⭐⭐⭐ |
| 团队学习成本 | ⭐(现有 Python 技能) | ⭐⭐⭐⭐(需全员转语言) |
| 微服务集成 | ⭐⭐⭐⭐(JSON/YAML 友好) | ⭐⭐⭐ |
对我们这种中小型服务(QPS < 5000),FastAPI 完全够用。省下的开发时间,够我多试三套婚纱了好吗!
最后:技术债 vs 婚礼债
写这篇文章的时候,已经是凌晨 1:30。窗外上海的夜还亮着,我的 FastAPI 服务刚刚通过全链路压测。虽然过程有点狼狈——比如上周五晚上因为 CORS 配置漏了,导致前端联调失败,被 PM 追着问“是不是要等到你结婚后再上线?”——但最终还是搞定了。
FastAPI 给我的最大感受是:现代、高效、不折腾。它不像 Django 那么重,也不像裸 Flask 那么原始。类型提示、自动文档、异步支持,这些特性让后端开发回归“写逻辑”本身,而不是和胶水代码搏斗。
当然,它也不是银弹。复杂业务还是要靠良好的架构设计,框架只是工具。但至少现在,我能安心去试妆了——毕竟,代码可以重构,婚纱只穿一次。
P.S. 如果你也正在备婚又加班,欢迎来 GitHub 给我点个 star(不是我的项目,是 FastAPI 的:https://github.com/tiangolo/fastapi)。算是给同病相怜的程序媛一点鼓励吧 💅

评论 0