FastAPI入门:Python后端开发新手指南

卓越的月亮
2025-12-15 20:14
阅读 648

上周五晚上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 定义两个表:BookBorrowRecord

# 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

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝