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

Gradle别卡了
2025-12-18 00:08
阅读 1690

上周五晚上十点半,我正蹲在县城老家的阳台上,一边啃着我妈刚蒸好的红薯,一边用 VSCode 调试一个接口。窗外是零星的路灯和偶尔路过的三轮车,而我的终端里却在疯狂刷着 422 Unprocessable Entity 的报错——那一刻我真的想把笔记本扔进隔壁池塘。

但转念一想,这不就是我最近准备跳槽、硬着头皮学 FastAPI 的日常吗?作为一个典型的“小镇做题家”,远程办公三年多,从 jQuery 写到 Vue3,前端动画搞了一堆,结果领导上个月突然甩过来一句话:“后端也得懂点,不然怎么和后端同学对齐?” 好吧,我承认,其实是我想跳槽去一线城市的大厂,简历上不能只有“精通 CSS 动画”这种听起来像美工的描述。

于是,FastAPI 成了我的新战场。今天这篇笔记,就是我踩坑、翻车、重装、再爬起来的真实记录。不讲虚的,全是实操。如果你也是和我一样的 Python 新手后端,或者正被面试题挑战逼得头秃,这篇或许能帮你少走点弯路。


为啥选 FastAPI?不是 Flask 吗?

说实话,一开始我也觉得 Flask 够用了。毕竟我们公司那个内部管理系统,用 Flask + SQLAlchemy 撑了两年多,连双11大促(虽然只是个本地电商节)都没崩。但问题来了——文档

产品经理每次提需求,都要问:“这个接口参数啥格式?返回啥结构?” 我只能截图 Postman 或者手写 Markdown。测试同事更惨,光靠肉眼核对接口字段,漏掉一个 is_vip 字段,上线后用户积分直接清零,运维半夜打电话骂我祖宗十八代。

FastAPI 最打动我的,是它自带 OpenAPI 文档 + 自动校验。你定义好 Pydantic 模型,接口文档自动生成,连 Swagger UI 都给你配好了。更狠的是,传参不对?直接 422 报错,连脏数据都进不了业务逻辑。

小镇做题家的觉悟:代码可以烂,但接口必须干净。


环境搭建:别让工具拖后腿

我在县城用的是联通 50M 宽带,pip install 经常卡死。所以第一步,先换源:

pip install fastapi uvicorn[standard] -i https://pypi.tuna.tsinghua.edu.cn/simple/

注意,一定要装 uvicorn[standard],否则静态文件、WebSocket 这些高级功能会报错。我第一次只装了 uvicorn,结果跑个 WebSocket 聊天室直接崩了,查了三天才发现是没装 websockets 依赖。

VSCode 插件我也堆满了:

  • Python
  • Pylance
  • REST Client(用来直接在编辑器里发请求)
  • Thunder Client(Postman 替代品,轻量)
  • Error Lens(把报错信息直接标在代码行上,救命神器)

启动服务?一行命令搞定:

uvicorn main:app --reload --port 8000

--reload 是开发模式自动重启,但千万别在生产环境开!我上周不小心把 dev 配置推到测试环境,结果每次有人 git push,服务就重启一次,运维差点把我拉黑。


第一个接口:从“Hello World”到面试题挑战

FastAPI 的 hello world 简直优雅到哭:

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"message": "县城码农在此"}

但现实哪有这么简单?上周面试一家杭州的公司,第一道题就是:“用 FastAPI 实现一个用户注册接口,要求邮箱格式校验、密码强度 ≥8 位、手机号唯一性检查。”

我当时心里咯噔一下——这不就是我最近练的题吗!

关键在于 Pydantic 模型。它不仅是数据载体,更是校验规则:

from pydantic import BaseModel, validator
import re

class UserCreate(BaseModel):
    email: str
    password: str
    phone: str

    @validator('email')
    def validate_email(cls, v):
        if not re.match(r"[^@]+@[^@]+\.[^@]+", v):
            raise ValueError('邮箱格式错误')
        return v

    @validator('password')
    def validate_password(cls, v):
        if len(v) < 8:
            raise ValueError('密码至少8位')
        return v

然后在接口里直接用:

@app.post("/register")
def register(user: UserCreate):
    # 这里已经自动校验过了,放心用 user.email
    if db.phone_exists(user.phone):
        return {"error": "手机号已注册"}
    db.create_user(user)
    return {"status": "success"}

重点来了:所有校验都在进入业务逻辑前完成。这意味着你的核心代码不用再写一堆 if-else 判断参数合法性——这不就是面试官想听的“防御性编程”吗?


数据库怎么搞?别再裸写 SQL 了

我们小县城项目之前用的是原生 SQLite + 手写 SQL,直到某次上线改了个字段名,忘了改查询语句,整个订单模块瘫痪两小时。自那以后,我发誓要用 ORM。

FastAPI 官方推荐搭配 SQLModel(作者也是 FastAPI 的 creator),它融合了 Pydantic 和 SQLAlchemy 的优点。比如用户表:

from sqlmodel import SQLModel, Field, create_engine, Session

class User(SQLModel, table=True):
    id: int = Field(default=None, primary_key=True)
    email: str = Field(unique=True)
    password: str
    phone: str = Field(unique=True)

engine = create_engine("sqlite:///./test.db")
SQLModel.metadata.create_all(engine)

插入数据?简洁到离谱:

with Session(engine) as session:
    session.add(User(email="a@b.com", password="12345678", phone="13800138000"))
    session.commit()

更爽的是,Pydantic 模型和数据库模型可以复用。你甚至可以直接把 User 当作接口响应模型返回(记得隐藏密码字段):

from pydantic import field_validator

class UserPublic(BaseModel):
    id: int
    email: str
    phone: str

    @field_validator('phone', mode='before')
    def mask_phone(cls, v):
        return v[:3] + '****' + v[-4:]  # 138****8000

性能与架构:别以为 FastAPI 快就乱来

FastAPI 基于 Starlette 和 Pydantic,异步支持一流。但很多新手(包括我)一上来就狂写 async def,结果数据库还是同步操作,性能反而更差。

记住:异步只在 I/O 密集型场景才有优势。如果你的接口主要在查数据库、调第三方 API,才考虑 async。否则,同步代码更简单、调试更容易。

我们线上环境用的是 Gunicorn + Uvicorn worker,配置如下:

gunicorn -k uvicorn.workers.UvicornWorker main:app -w 4 -b 0.0.0.0:8000 --timeout 60

为什么 4 个 worker?因为我们服务器是 4 核。别盲目加进程,上下文切换开销会让你哭。

另外,不要在接口里直接操作文件或长时间计算。有一次我写了个导出 Excel 功能,直接在接口里生成文件,结果并发一高,内存爆了。后来改成 Celery 异步任务 + Redis 队列,稳如老狗。


生产环境那些坑:运维不会告诉你的事

FastAPI 开发爽,但上线才是真正的考验。分享几个血泪教训:

1. 日志别只 print

开发时 print("debug") 很爽,但生产环境必须用 structured logging。我用的是 loguru

from loguru import logger

logger.add("logs/app.log", rotation="500 MB")
logger.info("User {} registered", user.email)

2. CORS 跨域问题

前端同事在 Vue 里调接口,一直报 CORS error。其实 FastAPI 有官方中间件:

from fastapi.middleware.cors import CORSMiddleware

app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://your-frontend.com"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

别偷懒写 allow_origins=["*"],会被安全扫描打回来。

3. 健康检查接口

K8s 或 Docker Swarm 需要 /health 接口判断服务是否存活:

@app.get("/health")
def health_check():
    return {"status": "ok", "db": "connected" if db.ping() else "down"}

资源推荐:小镇做题家的自学包

最后放点干货资源,全是亲测有效的:

类型 名称 说明
官方文档 FastAPI 官网 英文好,例子全,必看
中文教程 FastAPI 中文文档 翻译质量不错
视频课 Corey Schafer 的 FastAPI 系列 YouTube 免费,讲解细致
GitHub 项目 full-stack-fastapi-postgresql 官方推荐的完整项目模板
面试题 LeetCode “API Design” 标签 结合 FastAPI 实现

特别推荐那个 full-stack-fastapi-postgresql 项目,连 Dockerfile、Nginx 配置、用户认证、权限控制都给你写好了。我直接 fork 下来改,三天就搭出 MVP。


写在最后:从县城到大厂,代码是唯一的船票

学 FastAPI 这一个月,我刷了 30+ 道后端面试题,写了两个小项目,还帮公司重构了旧接口。上周四,终于收到一家深圳公司的二面通知——岗位是“全栈工程师”,要求熟悉 FastAPI。

我知道,县城的夜晚很安静,但代码跑起来的声音,比任何喧嚣都响亮。

FastAPI 不是银弹,但它让我这个前端出身的“伪后端”看到了希望:用现代工具,写清晰代码,做可靠系统。这不就是我们小镇做题家最擅长的事吗?

所以,别管你在哪座小城,只要终端还能连上 GitHub,键盘还能敲出逻辑,你就永远有机会。

对了,刚提交的 PR 又被测试打回来了——说手机号脱敏规则错了。得,红薯也凉了,继续改 bug 吧。

(完)

评论 0

最热最新
暂无评论
Gradle别卡了Lv.1
0
影响力
0
文章
0
粉丝