FastAPI入门:Python后端开发新手指南(一个被面试题逼出来的实战笔记)

Await等等我
2025-12-12 23:23
阅读 220

去年双11前夜,我还在深圳南山科技园加班到凌晨三点。不是因为要抢购,而是我们组的微服务突然挂了——用的是 Flask + RESTful 的老架构,接口响应慢得像蜗牛爬。运维小哥一边喝着红牛一边吐槽:“你这接口连个异步都不支持,QPS 跑不过 200 就别想上线了。”

我当时真的想砸电脑。

作为 GitHub Copilot 付费用户(快两年了,每月工资到账第一件事就是续费),我自认代码写得不差,但那会儿才意识到:光会写逻辑远远不够,架构和性能才是后端工程师的硬通货。尤其是在深圳这种腾讯、字节、Shopee 扎堆的地方,面试官张口就问“你用过什么高性能 Python 框架?怎么处理高并发?”——Flask 显然不够看了。

于是,我开始认真研究 FastAPI。原因很简单:它快、现代、自带 OpenAPI、原生支持 async/await,而且文档写得比某些产品经理的需求文档还清晰。更关键的是,最近半年我面了三家大厂,每一家都问到了 FastAPI 相关的面试题,比如:

“FastAPI 和 Flask 在异步处理上有何本质区别?”
“如何用 Pydantic 做数据校验来提升接口健壮性?”
“你们项目里怎么用 Dependency Injection 管理数据库连接的?”

今天这篇不是官方文档复读机,而是我踩坑、调优、上线后的真实实战经验分享,特别适合想用 FastAPI 找工作的 Python 新手。


为什么选 FastAPI?不是为了装 X

先说结论:如果你要做 API 服务,尤其是需要高性能、强类型、自动生成文档的后端系统,FastAPI 几乎是目前 Python 生态里的最优解

我司去年从 Flask 迁移部分核心服务到 FastAPI 后,接口平均响应时间从 320ms 降到 85ms(压测 QPS 从 180 提升到 1400+)。这不是魔法,而是 Starlette(ASGI)+ Pydantic 的组合拳打得好。

对比一下主流框架:

特性 Flask Django REST Framework FastAPI
异步支持 需第三方库 有限 原生支持
自动文档 无(需 Swagger 插件) 需 drf-yasg 内置 Swagger + ReDoc
类型提示 可选 强制推荐(Pydantic)
性能 中等 中等 极高(接近 Node.js)
学习曲线 中(需理解 async)

我们团队现在新项目一律用 FastAPI。就连那个总提“明天上线”的产品经理,看到自动生成的交互式 API 文档后都说:“这个比 Postman 好用多了,我自己都能测。”


实战:从零搭一个带 DB 的用户服务

别整 Hello World 了,直接上干货。假设我们要做一个简单的用户注册/查询接口,用 PostgreSQL + SQLAlchemy + Alembic。

1. 环境准备(别跳过!)

pip install fastapi uvicorn sqlalchemy asyncpg alembic python-dotenv

注意:一定要用 uvicorn 启动,别用 python app.py。前者是 ASGI 服务器,后者会把异步变同步,性能直接废掉。

2. 项目结构(我们团队的标准模板)

user-service/
├── app/
│   ├── main.py
│   ├── models.py      # DB 模型
│   ├── schemas.py     # Pydantic 校验模型
│   ├── database.py    # DB 连接池
│   └── api/
│       └── v1/
│           └── users.py
├── alembic/
└── .env

3. 关键代码解析(带注释版)

database.py —— 连接池配置(生产环境必看)

from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker

# 注意:asyncpg 是异步驱动,别用 psycopg2!
DATABASE_URL = "postgresql+asyncpg://user:pwd@localhost/userdb"

engine = create_async_engine(DATABASE_URL, echo=False, pool_size=20, max_overflow=30)
# pool_size + max_overflow 控制最大连接数,避免 DB 被打爆
AsyncSessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)

async def get_db():
    """Dependency Injection 用的 DB 会话"""
    async with AsyncSessionLocal() as session:
        yield session

schemas.py —— 数据校验(防前端乱传参数)

from pydantic import BaseModel, EmailStr

class UserCreate(BaseModel):
    username: str
    email: EmailStr  # 自动校验邮箱格式!再也不用手写正则了
    password: str

    class Config:
        orm_mode = True  # 允许从 ORM 对象自动转 JSON

api/v1/users.py —— 路由 + 业务逻辑

from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.future import select
from app.database import get_db
from app.models import User
from app.schemas import UserCreate

router = APIRouter(prefix="/v1/users", tags=["users"])

@router.post("/", response_model=UserCreate)
async def create_user(user: UserCreate, db: AsyncSession = Depends(get_db)):
    # 先查重(真实项目记得加索引!)
    result = await db.execute(select(User).where(User.email == user.email))
    if result.scalars().first():
        raise HTTPException(status_code=400, detail="Email already registered")
    
    db_user = User(**user.dict())
    db.add(db_user)
    await db.commit()
    await db.refresh(db_user)
    return db_user

main.py —— 入口文件

from fastapi import FastAPI
from app.api.v1.users import router as user_router

app = FastAPI(title="User Service", version="1.0")

app.include_router(user_router)

启动命令:

uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload

访问 http://localhost:8000/docs,你会看到自动生成的 Swagger UI —— 这玩意在联调时救了我无数次命。


面试高频考点 & 避坑指南

❌ 坑1:忘记用 async/await 导致同步阻塞

我见过太多人这么写:

def get_user(db):  # 同步函数!
    return db.query(...).all()

结果整个事件循环被卡住。所有 DB 操作、外部 API 调用都必须是 async

✅ 正确姿势:

  • asyncpgaiomysql
  • SQLAlchemy 2.0+ 支持真正的异步 ORM
  • 外部请求用 httpx.AsyncClient

❌ 坑2:Pydantic 模型没做验证,线上被恶意输入搞崩

曾经有个实习生没校验 page_size,有人传了 9999999,直接 OOM。现在我们团队规定:所有入参必须走 Pydantic 模型,并在 CI 里加了静态检查。

✅ 正确姿势:

class Pagination(BaseModel):
    page: int = 1
    size: int = 10

    @validator('size')
    def check_size(cls, v):
        if v < 1 or v > 100:
            raise ValueError('size must be between 1 and 100')
        return v

💡 面试题加分项:Dependency Injection

FastAPI 的 DI 系统超灵活。比如我们可以把权限校验抽成依赖:

async def verify_token(token: str = Header(...)):
    if token != "SECRET":
        raise HTTPException(401)
    return True

@router.get("/", dependencies=[Depends(verify_token)])
async def get_users(...):
    ...

这样路由干净,逻辑复用,面试时一说“我们用 DI 解耦了认证逻辑”,面试官眼睛都亮了。


最后:FastAPI 真的能帮你拿 Offer 吗?

上周五,我帮一个学弟改简历。他原来写“熟悉 Flask”,我直接改成“使用 FastAPI 构建高并发异步 API 服务,QPS 提升 7 倍”。结果第二天就收到了 Shopee 的面试邀约。

在深圳这片卷王之地,技术栈就是你的简历门面。FastAPI 不仅能让你写出更健壮、高性能的后端服务,更重要的是——它代表你关注现代工程实践,而不是停留在“能跑就行”的阶段。

当然,工具只是工具。真正值钱的,是你在 deadline 前修复线上 bug 的经验,是你设计表结构时考虑的扩展性,是你在代码 review 时对每一行 async 的执着。

FastAPI 很香,但别忘了:后端工程师的核心,永远是解决问题的能力

(P.S. 如果你也在用 FastAPI,欢迎交流~ 我的 GitHub Copilot 刚刚帮我自动生成了 80% 的 boilerplate 代码,省下的时间够我多喝两杯喜茶了 ☕️)

评论 0

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