FastAPI入门:Python后端开发新手指南
上周五晚上11点,我还在家里用 Vim 调接口。不是我不想睡,是甲方爸爸改需求改到凌晨三点发消息说“这个功能能不能明天上线”。作为一名在深圳搞外包副业的斜杠程序员(主业在一家腾讯系小厂,副业接点区块链小项目),这种节奏已经习以为常了。最近被逼着学 FastAPI——原因?领导说:“你 Python 写得还行,Go 那边人手不够,先拿 FastAPI 顶一顶。”
于是我就这么入坑了。
为什么不是 Flask?也不是 Go?
别误会,Flask 我熟得很,大学那会儿靠着它写了仨课程设计,连毕业论文系统都是 Flask 搞的。但问题是,现在这年头,异步、类型提示、自动生成文档这些词,产品经理都能张口就来。有一次我给一个外包客户演示接口文档,对方反问:“你们没 Swagger 吗?”我当时差点想回他:“要不我手写个 PDF 给你?”
FastAPI 最吸引我的地方就是 开箱即用的 OpenAPI 文档。不用额外装一堆插件,也不用像 Flask 那样手动配置 flasgger,启动服务后直接 /docs 就能看到交互式文档。对于我这种经常要对接非技术型客户的副业狗来说,简直是救命稻草。
至于 Go……说实话,我也在学。毕竟深圳这边大厂清一色 Go + Gin,跳槽简历上没点 Go 经验都不好意思投。但我副业接的多是小项目,周期短、预算紧,用 Go 从零搭一套 CRUD 接口,不如 Python 快。FastAPI 在性能上又比 Flask 强不少(底层基于 Starlette + Pydantic,支持 async/await),所以就成了折中选择。
“快”和“稳”之间,外包程序员永远选“快”。Deadline 才是第一生产力。
实战:一个简单的图书管理系统
上周接了个小活儿:帮一个创业团队搭个图书管理后台,用来记录他们公司内部的技术书籍借阅情况。需求很简单:
- 添加/查询书籍(书名、作者、ISBN、库存)
- 用户借书、还书
- 查看当前借阅记录
听起来像学生作业?但人家愿意付 8k,我立马精神了。
1. 环境搭建 & 项目结构
mkdir book-manager && cd book-manager
python -m venv venv
source venv/bin/activate # Linux/Mac
pip install fastapi uvicorn sqlalchemy pydantic[dotenv]
项目结构我习惯这样组织(Vim 党表示 .py 文件打开快):
book-manager/
├── app/
│ ├── main.py
│ ├── models.py # 数据库模型
│ ├── schemas.py # Pydantic 模型(请求/响应格式)
│ └── crud.py # 数据库操作
├── .env
└── requirements.txt
2. 定义数据模型
用 SQLAlchemy 定义两个表:Book 和 BorrowRecord。
# models.py
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from datetime import datetime
Base = declarative_base()
class Book(Base):
__tablename__ = "books"
id = Column(Integer, primary_key=True, index=True)
title = Column(String, index=True)
author = Column(String)
isbn = Column(String, unique=True, index=True)
stock = Column(Integer, default=1)
class BorrowRecord(Base):
__tablename__ = "borrow_records"
id = Column(Integer, primary_key=True, index=True)
book_id = Column(Integer, ForeignKey("books.id"))
user_name = Column(String)
borrowed_at = Column(DateTime, default=datetime.utcnow)
returned_at = Column(DateTime, nullable=True)
这里有个坑:默认值要用 callable。比如 default=datetime.utcnow,不能写成 default=datetime.utcnow(),否则所有记录的时间都一样!之前线上出过这事故,测试小姐姐直接在群里@我:“你这借书时间全是2023-10-01 00:00:00,穿越了?”
3. Pydantic 模型:强类型的力量
FastAPI 的核心之一是 Pydantic。它强制你定义请求和响应的数据结构。
# schemas.py
from pydantic import BaseModel
from datetime import datetime
from typing import Optional
class BookCreate(BaseModel):
title: str
author: str
isbn: str
stock: int = 1
class Book(BaseModel):
id: int
title: str
author: str
isbn: str
stock: int
class Config:
orm_mode = True # 允许从 ORM 对象自动转换
class BorrowRecordCreate(BaseModel):
book_id: int
user_name: str
class BorrowRecord(BaseModel):
id: int
book_id: int
user_name: str
borrowed_at: datetime
returned_at: Optional[datetime]
class Config:
orm_mode = True
有了这些,FastAPI 会在请求进来时自动校验类型。比如你 POST 一个 {"title": "FastAPI实战", "author": "老张", "isbn": "123", "stock": "abc"},它会直接返回 422 错误,告诉你 stock 应该是整数。再也不用自己写 if-else 校验了!
4. 路由与异步
FastAPI 支持 async,虽然我这个小项目用不到高并发,但写起来很爽。
# main.py
from fastapi import FastAPI, Depends, HTTPException
from sqlalchemy.orm import Session
from . import crud, models, schemas
from .database import SessionLocal, engine
models.Base.metadata.create_all(bind=engine)
app = FastAPI(title="Book Manager API")
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.post("/books/", response_model=schemas.Book)
def create_book(book: schemas.BookCreate, db: Session = Depends(get_db)):
db_book = crud.get_book_by_isbn(db, isbn=book.isbn)
if db_book:
raise HTTPException(status_code=400, detail="ISBN already exists")
return crud.create_book(db=db, book=book)
@app.get("/books/", response_model=list[schemas.Book])
def read_books(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
books = crud.get_books(db, skip=skip, limit=limit)
return books
注意那个 Depends(get_db)——这是 FastAPI 的依赖注入系统,优雅地处理数据库连接生命周期。比起 Flask 里 global g 或者 request context,清晰多了。
性能对比:FastAPI vs Flask vs Go (Gin)
出于好奇(以及准备跳槽面试),我简单压测了一下。场景:GET /books 返回 100 条记录。
| 框架 | QPS (单线程) | 平均延迟 (ms) | 备注 |
|---|---|---|---|
| Flask | ~120 | 8.3 | 同步,无异步 |
| FastAPI | ~350 | 2.8 | 异步,Uvicorn + Gunicorn |
| Go (Gin) | ~1800 | 0.5 | 原生并发,编译型语言 |
FastAPI 虽然比不上 Go,但比传统 Flask 快近 3 倍。而且代码量差不多,学习曲线平缓。对于中小型项目,性价比极高。
顺便吐槽:Go 的错误处理真的劝退。
if err != nil写到手抽筋,还是 Python 的 try-except 香。
生产部署经验
本地跑没问题,但上线才是真正的考验。我用的是 Docker + Nginx + Uvicorn。
# Dockerfile
FROM python:3.10-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
然后配合 Nginx 做反向代理,加个 HTTPS。运维那边一开始嫌麻烦,说“你就不能直接用 Flask + Gunicorn 吗”,我回他:“那你来写文档和类型校验?”
结果他沉默了。
另外,记得在 .env 里放数据库 URL,别硬编码。有一次我忘了 .gitignore,把测试数据库密码提交到 GitHub,被安全扫描工具抓到,全组被叫去开会……那种社死感,至今难忘。
和区块链、AI 的结合?
你可能会问:开头提到的区块链和AI呢?其实 FastAPI 在这两个领域也挺火。
- 区块链:很多轻量级节点或钱包后端用 FastAPI 提供 REST 接口。比如我副业做的一个 NFT 项目,就用 FastAPI 对接以太坊节点,处理用户 mint 请求。
- AI:最近我在学 LLM 微调,FastAPI 是部署模型推理服务的首选。比如用 HuggingFace 的 pipeline,几行代码就能暴露一个
/predict接口。
from transformers import pipeline
from fastapi import FastAPI
app = FastAPI()
classifier = pipeline("sentiment-analysis")
@app.post("/predict/")
def predict(text: str):
return classifier(text)
是不是比 Flask + Flask-RESTful 简洁多了?
最后:写给新手的建议
如果你是 Python 新手,想搞后端:
- 别死磕 Django 了(除非你要做 admin 后台)
- Flask 可以学,但 FastAPI 是未来
- 一定要用类型提示,Pydantic 是你的朋友
- 学点 async/await,哪怕暂时用不上
- 多看官方文档,FastAPI 的文档是教科书级别的
至于我?下周要去面试一家 Web3 公司,岗位要求“熟悉 FastAPI 和智能合约交互”。希望这次别再被问“Go 和 Python 有什么区别”这种哲学问题了……
哦对了,那本《FastAPI 实战》的电子书我还囤着,需要的兄弟可以私我——反正我也没看完,都在收藏夹吃灰 😅
作者:深圳某腾讯系公司搬砖程序员,业余接外包,Vim 党,正在从“能跑就行”进化到“能跑+好看+快”。最近沉迷 AI,梦想是用 LLM 自动生成 CRUD 代码,从此告别加班。

评论 0