🟡 进阶

FastAPI 是什么、为什么首选它

它是 Python 里现在最流行的「写接口」的工具。这篇不教你写代码,教你判断:网上那句「首选 FastAPI」指的是什么、在什么条件下成立、什么条件下它反而会让你多花时间和钱。

📅 更新于 2026-09-23

本文校对于 FastAPI @ 0.141.1 · 官方源:fastapi.tiangolo.com

0.141.1
本文校对时的最新版本(2026-07-29 发布)
3.59 亿
上个月从 PyPI(Python 的官方应用商店)被下载的次数(口径见 §07)
6 行
跑通第一个接口的全部代码
2 层
它站在两个现成组件肩上——这既是它「快」的原因,也是「快」的上限

0030 秒速览:三句话,和你的第一个动作

读完这篇你能做到两件事:① 用一句人话说清 FastAPI 是什么、它和 Flask / Django(Python 里另外两个做网站和接口的常用工具)差在哪;② 判断「首选 FastAPI」这句话对你手上那个项目到底成不成立——包括它在什么条件下不成立。

如果只记三句话

🎯 记住了,后面都是细节

① FastAPI 是 Python 里专门用来「写接口」的工具。接口(也叫 API)就是别的程序来找你要数据时敲的那个窗口。它不是后端本身,只是后端最外面那道窗口——后面管数据的、算逻辑的,都不归它管。

② 它真正的卖点不是「快」,是「你写一遍,它同时给你三样东西」:在窗口自动拦下填错的单子、给前端同事看的自动文档页、以及一份别的程序能直接读懂的标准格式说明。第三样最被低估,因为它不可能和代码不一致——它是从代码里长出来的。

③ 网上说「首选」,前提是「你在用 Python」加「你要做的是给程序调的接口」。这两条任缺一条,这句话对你就不成立。缺第一条(团队不写 Python)它会让你多养一套技术栈;缺第二条(你要的是一个给人看的网站)你会发现它连登录页和后台管理都得自己搭。

接下来 60 秒:你的第一个动作

打开终端,粘这三行(第一行是检查版本,第二行是装包,第三行是起服务):

python3 --version
uv add "fastapi[standard]"
uv run fastapi dev

终端会打印出一个 http://127.0.0.1:8000/docs 的地址。把它粘进浏览器——你会看到一个能直接点、能直接试的接口文档页。这一步值的不是那三行命令,是你亲眼看到「文档不是我写的,是它自己长出来的」。完整走查(包括怎么故意让它报错)在 §06。

⚠️ 这篇假设你手上已经有这两样

① 一台能跑命令的电脑,上面装了 Python 3.10 或更高版本。没有的话先用 python3 --version 看一眼——低于 3.10 装不上当前版本的 FastAPI。从零开始装 Python 看本仓的 Python 快速上手。
② 一个你愿意放代码的空文件夹。本文§05 会带你建一个,不需要你已经有一个项目。

关键数字(先有个量级感)

3.59 亿次/月它上个月在 PyPI(Python 的官方应用商店)被下载的次数。同月 Flask 约 1.32 亿、Django 约 0.41 亿
10.2 万GitHub 上的收藏数(star),2026-09-23 当天实测
6 行第一个能跑的接口的代码量,一个字符都不用多写
2 套它自动生成的文档界面:/docs(能点能试)和 /redoc(适合通读)
≥3.10当前版本要求的 Python 版本;3.8 和 3.9 的支持都已经被移除
📖 这篇为什么值得读(它和别处的 FastAPI 教程差在哪)

网上的 FastAPI 入门文章几乎都写给「已经会写代码的人」看:默认你会写 Python、懂异步。这篇的起点不一样——它假设你懂行业、不写代码,手上有几个半途停下的项目,正在判断「AI 建议我用 FastAPI,这话能不能信」。所以它把重点放在四样别处不容易凑齐的东西上:官网那句「和 NodeJS、Go(另外两种常用来写后端的语言)一样快」的原始口径(连同它官网脚注里的星号)、官方 benchmark 页(官方自己的跑分测试页)承认的分层限制、一家公司真实的内存与云账单事故、以及 PyPI 下载量这个数字能证明什么、不能证明什么。

01先搞清楚一件事:FastAPI 名字里的「API」到底是什么

要理解 FastAPI,先得有一个「接口」的准确画面。这里用一个你一定经历过的场景。

接口就是餐厅的点单窗口

你去一家餐厅,不可能冲进后厨自己炒菜。你走到点单窗口,照着菜单说「一份宫保鸡丁,微辣少盐」,然后拿号、坐下等,最后从窗口把菜接走。

这个窗口就是接口(英文 API,全称「应用程序编程接口」——这个名字很唬人,但它描述的正是这件事:两个东西之间约定好的一个交界口)。

把它逐样对上,你就不需要再记任何新词:

餐厅里的东西接口世界里的名字为什么这个位置重要
点单窗口接口 / API唯一的进出口。窗口外的顾客和后厨互不打扰,所以后厨换主厨,顾客第二天照样来
菜单接口文档没有菜单,顾客只能瞎点。文档写错,来的单子就全是错的
你递进去的订单纸条请求(request)纸条上写什么,后厨就照着做什么。写漏了规格,做出来的就不是你要的
窗口递出来的菜响应(response)顾客只看得到这个。里面对不对,取决于订单和后厨
纸条必须按固定格子填JSON(一种固定写法的文本格式)格子的存在是为了让机器能读懂。人对格式不敏感,机器极度敏感
🔍 这个类比到哪里就不准了

餐厅里点单的是人,窗口后面也是人。接口世界里,点单的通常是另一个程序(你手机上的 App、网页、或者一个 AI 助手),后厨也全是程序。
这处差异带来一个真实后果:程序不会像人那样「不懂就问」。你把订单纸条上的「少盐」写成「少严」,人会问你一句,程序会直接照着做或者直接崩。所以接口世界对「格式对不对」的要求,比餐厅严得多——而这正是 FastAPI 要替你解决的头号问题。

为什么以前跟开发「对接口」,对的就是这个

你大概经历过这种场面:开发说「接口文档发你了,你按这个调」,然后你打开一个密密麻麻的网页,上面写着地址、参数、返回示例。那个网页就是这个窗口的菜单,而FastAPI 最出名的能力之一,就是让这份菜单自动生成。这一点在 §03 展开。

先记住一句:接口是一个「交界口」,不是一个「系统」。这句话会在 §07 变成你判断「该不该用 FastAPI」的第一把尺子。

02FastAPI 是什么:一句话,和它的四个「不是」

概念类的名词,最快搞懂的办法是先划掉它不是什么。

✗ 它不是「后端」

后端是一整套东西:接口、业务逻辑、数据库、定时任务、权限。FastAPI 只管最外面那道窗口——收请求、检查格式、把结果发回去。窗口后面那一切,它不负责。

✗ 它不是「数据库工具」

它不存数据,也不管你怎么存。它只在数据进出窗口的那一瞬间做检查。所以「用 FastAPI 是不是就不用选数据库了」这个问题的答案是:不,你得单独选,它只是不拦着你。

✗ 它不是「网站」

它默认不生成页面。它吐出来的是给程序读的数据(那种固定格式的文本),不是给人看的网页。要给人看页面,得另外接一个前端,或者换成 Django 那条路。

✗ 它不是一种语言、也不是一个平台

它是用 Python 写的一套工具,装在 Python 环境里跑。它不是「另一个 Python」,也不是要注册账号的云服务。

那它是什么

🎯 一句话定义

FastAPI 是一个用 Python 写接口的「框架」(框架=一套已经搭好的骨架和规矩):你用 Python 自带的类型标注(也就是写名字时顺手注明「这里装的是文字还是数字」)描述「这个窗口收什么、回什么」,它负责照这份描述去检查每一单、并自动生成给人和机器看的说明书。

这句话里有两个词要拆开,拆完就没有生词了。

「框架」是什么,为什么不干脆直接写

框架就是一套已经搭好的骨架和规矩。回到餐厅:你可以从零开始盖一间厨房、砌灶台、定菜单格式、设计订单纸条;也可以租一个已经盖好的厨房,里面灶台、出菜口、洗碗池都到位了,你只需要决定「有人点宫保鸡丁时该怎么做」。

框架就是那个租来的厨房。它的价值在于:那些每道菜都要用的东西(窗口、菜单格式、订单纸条的格式),它已经做好且做了上千遍;你只写你这个项目独有的那一部分。代价是你要按它的规矩来——灶台的位置不能自己挪。

「类型标注」是什么,为什么它是 FastAPI 的地基

类型标注就是你在给一个名字起名的时候,顺手注明它装的是「文字」还是「数字」。比如你写「订单号」,你同时说明「这里的订单号是一个数字」。这在 Python 里是一行很短的写法,不需要学新语言。

这看着像废话,但对机器不是。因为一旦你注明了「订单号是数字」,FastAPI 就能替你做到三件事:检查每一单的订单号是不是真的数字;把这件事写进说明书;以及检查通过后把它交给你时,确认它已经是数字而不是一串文字。你只说了一遍,三件事一起办。

这也解释了它名字里的一半:Fast。它有两层意思,多数人只看到一层——

哪一层「快」官方原话你该怎么用这一层
开发快(写代码的人快)官网称「把开发功能的速度提高约 200% 到 300%」「减少约 40% 的人为错误」,但脚注写明这是它自己内部开发团队做产品应用时的估计当成「方向性说法」,不是研究结论。厂商自测的数字,凡带星号的都该这么读
运行快(程序跑得快)官网称「性能与 NodeJS 和 Go 相当(得益于 Starlette 和 Pydantic)」「最快的 Python 框架之一」Starlette 和 Pydantic 是它脚下的两层现成组件——一个负责分派请求、一个负责核对数据,§04 会拆开。这句话的边界在 §09 拆——它比你想的窄得多

如果只能带走一句:FastAPI = 用 Python 自带的「注明类型」这个动作,换来自动检查 + 自动说明书 + 自动格式转换。你付的是「多写几个字」,换回来的是三件本来要手工做、而且一定会忘掉其中一件的事。

03如果没有它,你要自己做哪三件苦工

「它解决什么问题」这个问题,最好的问法是反过来问:不用它,会发生什么?答案是三件苦工,其中第三件是最要命的。

苦工一:从一堆乱七八糟的输入里,把你要的东西一个个抠出来

顾客递进来的订单纸条不会那么规矩。订单号可能是数字、可能是文字、可能压根没填、可能是空的、可能多写了一个字段。如果没有人替你在窗口做检查,那这段检查代码就要你自己写——而且要在每一个接口里写一遍。

苦工二:判断每一格填得对不对,错了还要组织一句错误说明

「这个字段必须是数字」「这个必须是 1 到 100 之间」「这个字段没填就默认 10」。这些规则要一条条写下来(这种「按规矩逐格核对」的活,行业里叫校验),还要决定:填错了到底回什么?回一句人话,还是一堆英文报错?

苦工三(最要命):写一份和代码永远一致的说明书

前两件苦工,累但看得见。第三件是隐形杀手:你要手工写一份接口文档,而且以后每次改代码,都要记得回来改文档。

人一定会忘。于是最常见的场景是:文档上写着这个字段可以不填,实际上代码早就改成必填了。前端同事照着文档写,一调就报错,然后大家花半天找原因——找的不是 bug,是过期文档。

✗ 手工维护的文档

文档是另一份文件。代码改了,文档不会跟着动。它俩谁对,没人知道,只能去问写代码的人。三个月后写代码的人也忘了。

✓ 从代码里长出来的文档

文档不是一份文件,而是每次程序启动时,照着代码里的描述现场算出来的一页网页。代码改了,它跟着变。它没有「过期」这个状态,因为它根本没有第二份。

💡 这一条对你这种角色最值钱

你不需要读代码,也能靠这页文档做三件事:① 验收——AI 说「接口做好了」,打开这页文档,看那个接口在不在、收什么、回什么;② 自己试——页面上可以直接填参数点一下就把请求发出去,不用等开发给你写测试页面;③ 给前端交接——把这页地址发过去,双方看的是同一份东西,吵架时它有裁判作用。

所以「自动文档」不是省了写文档的时间,它换掉了一个会骗人的东西。这是本文认为 FastAPI 最被低估的一项能力,没有之一。

这三件苦工,它分别怎么接走

本来要你做的FastAPI 的做法你需要为此额外学什么
从输入里抠参数、判断有没有传看你写的那段处理步骤(函数)是怎么声明的,自动把对应位置的输入取出来不用额外学,写清楚「要什么」就行
写校验规则、组织错误说明照着你的类型标注检查;不符就自动回一个标准的错误回应,附上「哪个字段、错在哪」不用额外学规则语法,标注写细一点即可
手工写并维护接口文档自动生成两套网页界面,外加一份机器能读的说明书知道去哪个地址看(/docs)即可

04拆开看:真正干活的是三层,FastAPI 只是最上面那层

这一节是全文最「技术」的一节,但它回答两个你一定会遇到的问题:为什么它说自己快?以及,那句「快」到底在夸谁?

三层套娃

Uvicorn
听门的人
→
Starlette
分单的人
→
FastAPI
管规矩的人
这一层它管什么(用餐厅的话说)为什么它不被你直接看见
Uvicorn(一类叫「ASGI 服务器」的程序,你只要理解成「专门负责收发网络请求的那道门」)听门:守在你这台机器的一个固定门牌号(端口)上,把外面发来的请求收进来、把结果发出去。它不懂你的业务因为它只干「收发」,你永远不用为它写业务代码。它是一类程序的通称,Uvicorn 是其中最常用的一个
Starlette(一个只管分单的轻量工具)分单:看地址决定这单该交给哪段代码处理(这叫「路由」)因为它提供的能力很基础,单独用要自己补很多活。FastAPI 把它整层包了进去
Pydantic(数据校验库)核对订单:把收到的文本按你声明的格式逐格对一遍,不符就报错因为它只在「数据进出」的那一刻出现,平时不刷存在感
FastAPI管规矩:把上面三样粘起来,再加自动文档、权限、依赖管理这些「做接口总要用到」的东西——它是你唯一直接打交道的那层

这个结构推出一个结论,它会让一句流行话当场缩水

既然 FastAPI 建在 Starlette 之上、Starlette 又建在 Uvicorn 之上,那就有一个绕不过去的数学事实:最上面那层不可能比下面那层快。每多一层,就多一层开销。

这不是本文的推测,是 FastAPI 官方 benchmark 页面自己写的原话,大意是:独立 benchmark 显示,跑在 Uvicorn 上的 FastAPI 是最快的 Python 框架之一,但它只低于 Starlette 和 Uvicorn 本身;并且 Uvicorn 只是一个负责收发的程序、Starlette 只是负责分单的那一层,拿它们和 FastAPI 一起排名的榜,本身就不该直接读。

🔍 那「和 NodeJS、Go 一样快」到底在说什么

它说的是框架这一层额外加的开销很小——小到在那些 benchmark 里,和用 Node.js、Go 写的同规模示例拉不开明显差距。它不是说「你的应用会和 Go 写的一样快」。你的应用慢,通常慢在三个地方:数据库查询、调用外部服务(包括调用 AI 模型)、以及写了会卡住的代码。这三处和你选哪个框架基本无关。

这个区分在 §09 会变成一句你可以直接拿去问 AI 的话。

05装好、跑起来:三分钟看到那一页自动文档

理论到此为止。这一节只有动作。

⚠️ 动手前先确认这两样

① Python 3.10 或更高。先在终端跑 python3 --version 看一眼。如果低于 3.10,当前版本的 FastAPI 装不上——先用本仓的 Python 快速上手 把 Python 装好。
② 一个空文件夹。下面第一步就会建。

1
先看版本,确认底线
python3 --version
# 需要看到 3.10 以上。本文校对时 FastAPI 的底线就是 3.10
2
装 uv(官方文档推荐的第一步)

uv 是一个装和管理 Python 包的工具(一个项目要用到的那些现成包,行业里叫它的「依赖」)。三种装法挑一种,Mac 用户最省事的是第二种:

# 官方安装方式(macOS / Linux 通用)
curl -LsSf https://astral.sh/uv/install.sh | sh

# Mac 上更省事的一种:Homebrew
brew install uv

# 如果你已经有 pipx
pipx install uv
3
建一个空项目,把 FastAPI 装进去
uv init my-api
cd my-api
uv add "fastapi[standard]"

注意两点:fastapi[standard] 要带引号(官方文档专门提醒过,不带引号在某些终端里会被拆坏);方括号里的 standard 意思是「连同日常开发要用的那几样配件一起装」——包括下面那条起服务的命令。

4
不想用 uv?pip 也行

官方给了替代路径,前提是先进一个隔离的 Python 环境(这一步的意义见本仓的 虚拟环境是什么):

python3 -m venv .venv
source .venv/bin/activate
pip install "fastapi[standard]"
5
起服务,看那三行输出
uv run fastapi dev

你会看到这样一段,重点看里面三行:

Serving at: http://127.0.0.1:8000
API docs:  http://127.0.0.1:8000/docs
Running in development mode, for production use: fastapi run

第三行的意思是:现在这个模式是给你自己开发时用的(它会盯着文件改动自动重启),真正上线要换另一条命令。这个区分在 §10 不值得单独讲,但你要知道有这么个切换。

那三条输出分别是什么意思

输出它是什么你要拿它做什么
http://127.0.0.1:8000服务只开在你这台机器自己上。127.0.0.1 是一个固定写法,意思是「本机」,别人从外网访问不到先确认「它真跑起来了」。这一步出问题,后面都不用看
http://127.0.0.1:8000/docs自动生成的接口文档页,下面 §06 的主角打开它。这是你以后验收 AI 成果的主要工具
fastapi run上线时用的启动命令记住有这么回事即可,本地开发不用它

怎么关掉它

在那个终端窗口按 Ctrl + C。这是所有这类本地服务的通用关法——看到「服务跑了、终端没反应了」,第一反应该是它正占着这个窗口。

06最小例子:6 行代码,到一个会拦错数据的接口

这是官方文档里的最小示例,一个字都没改(只加了中文注释)。把它存成 main.py,放在 §05 建的那个文件夹里。

🔍 先认识代码里那个 GET,后面就不卡了

@app.get 里的 GET:请求的类型。GET 是「我要读数据」,POST 是「我要提交数据」。你不用记住全部类型,只要认得这一对、知道它出现在哪一行即可。

第一版:6 行,一个「你好世界」接口

from fastapi import FastAPI

app = FastAPI()


# 这行的意思是:有人访问网站根地址 / 时,交给下面这个函数处理
@app.get("/")
async def root():
    return {"message": "Hello World"}

跑起来:

uv run fastapi dev

然后打开浏览器,依次访问这三个地址。三个都值得看一眼:

地址你会看到什么它的用途
/一行文字:{"message": "Hello World"}确认接口通了。这就是「响应」,机器读的一段文本
/docs一个带折叠面板的网页,每个接口都能展开、能直接填参数点「Execute」你以后最常用的一个地址:验收、自己试、给前端看
/redoc同一份内容的另一种排版,适合从头读到尾要通读全部接口时用它,比 /docs 清楚
/openapi.json一大段机器读的文本,开头是 "openapi": "3.1.0"给别的程序读的说明书。很多工具能拿它自动生成调用代码
🔍 OpenAPI 和那两页文档是什么关系

OpenAPI 是一份公开的标准,规定「接口说明书该怎么写」,好让全世界的工具都能读懂。FastAPI 照着这份标准,从你的代码里算出一份说明书(就是 /openapi.json 那段文本);/docs 和 /redoc 则是两个现成的工具,把那份说明书渲染成网页给你看。
所以准确说法是:它生成的是一份标准格式的说明书,那两页网页只是说明书的两种显示方式。这也是为什么「用 FastAPI 的项目,文档不可能过期」——网页上没有一行字是手打的。

第二版:加一个参数,看它自动拦错

现在把代码换成下面这样——多了一个「把订单内容交给我」的数据结构,和一条带订单号的接口:

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()


# 这是在声明:一份订单必须有两格——title 是文字,size 是数字
class Item(BaseModel):
    title: str
    size: int


# 路径里的 {item_id} 是占位符;写 int 就是说「这里必须是数字」
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
    return {"item_id": item_id, "q": q}


@app.post("/items/")
def create_item(item: Item):
    return item

重启服务后(fastapi dev 会自动重启),做三件小事——这三件事就是「它到底帮你挡了什么」的现场:

1
正常访问一次

打开 http://127.0.0.1:8000/items/5?q=somequery,你会拿到:

{"item_id": 5, "q": "somequery"}
2
故意填错一格,看它拦下来

在 /docs 里找到 POST /items/,点「Try it out」,把请求内容改成下面这样(size 故意写成文字),点「Execute」:

{
  "title": "towel",
  "size": "XL"
}

它不会崩,也不会返回一个乱七八糟的结果,而是回给你一个标准错误,里面明确写着哪个字段错了、错在哪。这类「请求本身有问题」的回应,行业里约定用编号 422 表示。这类编号的规律值得你记一下:4 开头=问题出在这次请求上(404 是「你要的东西不存在」,422 是「你填的格式不对」);5 开头=服务端自己出了没接住的错(500 就是「程序崩了」)。以后看到编号,先看第一位,就能判断该找谁。

💡 你亲手做的就是一次校验测试

你没有写一行检查代码,它自己拦住了。以后 AI 说「接口做好了」,你就照这个动作做一遍——这一步能挡掉相当一部分「看起来做好了其实没做校验」的交付。

3
回头看 /docs 变了什么

刷新 /docs:新接口出现了,而且它明确标出了「这个字段是文字、那个字段是数字、哪个必填」。你没有写文档,文档跟着代码长出来了。

如果你打算让 AI 来写,把这段任务卡直接粘给它

这份模板的价值在于它把「验收条件」一起写进去了——AI 交活时你能照着核:

请用 FastAPI 给我做一个「查询订单状态」的接口,写在 main.py 里。

要求:
1. 用 Python 3.12 + FastAPI,依赖用 uv 管理;
2. 地址是 GET /orders/{order_id},其中 order_id 必须是数字;
3. 订单号不存在时,返回 404 和一句中文说明,不要让它变成 500;
4. 用一个 Pydantic 模型描述返回内容:订单号、状态、金额、下单时间;
5. 每个处理函数上面写一行中文注释,说明「它收什么、回什么、什么情况会报错」;
6. 以后要接数据库,所以请把「查数据」那一段单独抽成一个函数,别混在接口里;
7. 请把 FastAPI 的版本号写死,不要用「最新版」。

拿到代码后,你用四个问题验收,全程不需要读懂代码:

① 打开 /docs,这个接口在不在?
不在,就是没接上。这一步能挡住「代码写了但服务没跑起来」。
② 故意访问 /orders/abc(一个不是数字的订单号),它回的是 422 还是一大堆英文报错?
回 422 说明校验生效了;回 500 或者一屏英文堆栈,说明类型标注没写对,或者被改成了「什么都接受」。
③ 访问一个肯定不存在的订单号,它回的是 404 加一句人话吗?
如果回 500,说明「查不到」这种情况没被处理——这在真实使用里会变成一个看起来像「系统崩了」的假象。
④ 处理函数写的是 async def 还是 def?里面每一个调用都是「原生异步」的库吗?
这一问不需要你自己判断,直接把问题原样问 AI:「里面每一个调用都是原生支持 await 的库吗?只要有一个不是,就改回 def。」为什么必须问,见 §10 第一件事——这是本文认为最容易吃亏的一个坑。

07「为什么首选」这句话,适用范围在哪

这是全文最该慢慢读的一节。因为「首选」这两个字,是你在跟 AI 讨论技术方案时最容易照单全收、也最容易付代价的一句。

先把那句原话和它的口径摊开

官网首页的原始表述是这几句(本文照抄,附自己的翻译):

⚠️ 那个星号写的是什么

官网在页面底部对星号做了解释,原话大意是:这些估计基于它自己内部开发团队构建生产应用时的测试。

这不是说数字是假的,而是说它的性质是厂商自测,不是第三方独立研究。它没有对照组、没有公开方法、样本就是它自己团队的几个项目。正确的读法是「这个方向大概靠谱」,不是「我用了就能快三倍」。本文把这一点专门写出来,是因为你在别处看到这句话时,星号和脚注基本都被省掉了。

「首选」成立要同时满足四条

把这四条当成一张清单,逐条对你手上的项目打勾。缺任何一条,这句话对你就打了折扣。

#条件不成立时会发生什么
①你在用 Python(或者已经决定用 Python)团队是 Java / Node / Go 技术栈。这不是「选个框架」,这是「多养一套语言和技术栈」——多一套依赖管理、多一套部署方式、多一类要招的人
②你要做的是「给程序调的接口」,不是「给人看的网页」你要的是一个有登录、有页面、有后台管理的网站。FastAPI 只给你窗口,页面、账号体系、管理后台都得自己一样样拼
③有人能跟上「注明类型」和「管依赖」(维护项目用到的那批现成包,别让它悄悄变旧或互相冲突)这两件事写代码的人(或 AI)写出来的东西类型标得含糊,那 FastAPI 的三大好处会一起失效:校验拦不住、文档看着像有其实没用、错误提示帮不上忙
④你能接受它版本动得快见 §10 第三件事:它已经发布过 317 个版本,而且最近连着砍掉了两个 Python 旧版本的支持。想「装一次放两年不管」,它不合适

给「首选」补上缺掉的主语

网上那句话完整的版本其实是这样,只是主语经常被省略:

🎯 把话补完整

「在 Python 生态里,如果你的目标是给别人提供一个接口,FastAPI 是目前的首选。」

它不是「所有后端项目的首选」(那就把 Django 的位置占了),也不是「所有语言里的首选」(那就把 Java、Go、Node 的位置占了),更不是「小项目更快出成果的首选」(一个几十行的小程序(脚本)为了它要建一整套环境,反而更慢)。

它到底有多流行:三个数字,和每个数字的口径

「首选」这种说法需要流行度支撑。下面三个数字都是 2026-09-23 当天实测的,但每个数字能证明什么,比数字本身重要。

数字它是什么能证明什么 / 不能证明什么
3.59 亿次/月FastAPI 上个月在 PyPI 被下载的次数。同月:Flask 约 1.32 亿,Django 约 0.41 亿能证明生态大:遇到问题好搜到答案,AI 对它也更熟。不能证明「它最适合你」——这个数字里包含大量自动构建机器的重复下载,以及「别的包依赖它、被捎带装上」的情况。它衡量的是被安装,不是被选为新项目
10.2 万 starGitHub 上的收藏数能证明关注度高、社区活跃。不能横向比框架优劣——Django 起步早得多,star 的积累节奏完全不同
317 个版本它从发布至今累计的发行版本数能证明维护非常勤。同时也是条件④要你评估成本的原因:勤更新意味你要跟上
🔍 一个诚实的对照:Django 的下载量只有它的九分之一

按上面那组数字,Django 的月下载量大约是 FastAPI 的九分之一。但 Django 自带的东西 FastAPI 一样都没有:现成的管理后台(不用写页面就能增删改查数据)、完整的账号与权限体系、操作数据库的成套工具(这类工具叫 ORM,作用是让你不用手写数据库语句)。

所以这两个数字不能推出「FastAPI 好九倍」。它们更可能说明的是:现在有大量项目只做接口这一层(前端和数据服务分开的架构变主流了),而这类活正是 FastAPI 的地盘。你该问的不是「谁下载多」,而是「我要建的,是窗口还是整套房子」。

结论:这句话在你的决策里该怎么用

把它从「结论」降级成「一条信息」——它告诉你「在这个特定场景里,有一个被广泛验证过的默认选项」。你还需要自己补两个判断:我这个场景是不是那个场景(四条清单);以及,我为了用它要额外付什么(§10)。

08该用 / 不该用:按你手上有的东西对号入座

这一节是场景索引——读第二遍时直接从你这行找起。

你现在的状态建议下一步看哪
要用 AI 做一个「数据服务」:给前端页面、App、或者另一个 AI 助手提供数据它就是默认选项,直接开工§05 → §06
要做一个人用的网页:有登录、有页面、有后台管理Django 更省事——它自带这些。用 FastAPI 你得一样样拼§09 第 5 条
想临时给一个几十行的小程序套个接口,自己看看结果可以,但要接受「为它建一整套项目环境」。别指望五分钟搞定§00 的第一个动作
团队已有 Flask 项目在稳定跑别为了新而新。迁移的收益通常小于风险§09 第 4 条
团队里没人写 Python,也没有计划学「首选」这句话直接不成立。先解决语言问题§07 条件①
想要「接口 + 定时任务 + 消息队列 + 后台」一次做完FastAPI 只管接口那一段。要么另找一套全家桶,要么接受自己拼装§02 的四个「不是」
是想让 AI 帮忙做一个能演示的原型,跑通就行合适。它的自动文档页本身就是最好的演示物§06
项目要长期维护,但没人跟踪依赖升级先想清楚谁来跟版本,否则见 §10 第三件事§10

明确不该用的四种情况

🚫 遇到这四种,先别上

① 团队不写 Python。这是最贵的一条错误:不是多装一个包,是整套技术栈翻倍。

② 你需要的是「一整套房子」而不是「一个窗口」。把 Django 能白送的东西(后台、账号、页面)当成 FastAPI 的待办事项列表,你会发现工作量比想象大得多。

③ 项目本来就很小,而且只要一次。用它的成本包含建项目、管依赖、学它的规矩——一次性脚本不值得。

④ 没人能审代码,也没人能跟版本。它更新很勤,长期放着不动会慢慢落到「装不上新版、又不敢升」的尴尬位置。

09五个最容易信的说法,逐个对一遍

这五句话你大概率已经在别处见过。每一条都附上「它原本在说什么」和「你该怎么复述」。

误解 1:「它和 Node.js、Go 一样快」

它原本在说什么:官网原句是「性能与 NodeJS 和 Go 相当(得益于 Starlette 和 Pydantic)」。而官方 benchmark 页面自己补充了三件事:这是框架这一层的开销比较;FastAPI 不可能比它下面的 Starlette 快,Starlette 不可能比 Uvicorn 快;把负责收发的程序、只管分单的那一层、和完整框架混在同一张榜上排名,读法要特别小心。

你该怎么复述:「它自己额外加的开销很小。」

为什么这个误解很诱人:因为「快」是最好传播的一个词。而真实世界里你的应用慢,通常慢在数据库查询、调用外部服务(比如调用 AI 模型)、或者某个会卡住的写法上——这三处换任何框架都一样。把「框架快」当成「应用快」,会让你在真正该优化的时候看错地方。

误解 2:「加上 async 就一定更快」

它原本在说什么:官方文档给的规则完全不是「都用 async」,而是一张对照表(下一节展开):你调用的库支持异步,就用 async def;不支持,就用普通的 def;不知道,就用 def。

你该怎么复述:「用哪种写法,取决于你调的库,不取决于你想不想快。写错了会拖慢整个服务,不是拖慢这一个请求。」

这条是本文认为最容易造成真实损失的一条,所以它在 §10 排第一。

误解 3:「有自动文档,就不用写接口文档了」

它原本在说什么:自动生成的那页,内容是「有哪些接口、每个接口收什么字段、什么类型、哪些必填」。

它给不了什么:这些字段为什么存在、什么业务场景下该传什么值、这个状态码(422、404、500 这类编号)背后的业务含义是什么、出错时用户该看到什么。这些是业务规则,机器推不出来。

你该怎么复述:「它消灭的是『文档和代码不一致』这个问题,不是『写文档』这件事。」

顺带说,这一条对你的实际影响是正面的:机器能生成的那部分不用你操心,你该负责的正好是它生成不了的那部分——业务规则。这是一个很舒服的分工。

误解 4:「网上都说首选,所以我就该用」

它原本在说什么:那句「首选」有主语和前提,见 §07 的四条清单。

你该怎么复述:「在 Python 里做接口,它是默认选项。我这件事是不是那个场景,得我自己核。」

为什么这个误解很诱人:因为它省事。「首选」听起来是一个已经替你做完的判断,而它其实只是一个起点。本文把整节 §07 给它,就是因为这四个字的省略成分太多了。

误解 5:「它和 Django 是一个位置上的东西,只是更新」

它原本在说什么:这两个东西不在一个位置上。Django 是一整套后端方案(页面、后台管理、账号权限、数据库工具都有,适合「建一个网站」);FastAPI 是接口这一层的专用工具(适合「建一个数据服务」)。

你该怎么复述:「Django 是整套房子的装修方案,FastAPI 是一个特别好用的接活窗口。」

“更新”也不构成理由。Django 同样是活跃维护的项目,当前版本 6.1.1(2026-09-02 发布),FastAPI 是 0.141.1(2026-07-29 发布)——两者都在持续更新,只是各自解决的形状不同。

顺手放在一起的一个近亲,省得你以后混

名字本文校对时的版本它在什么位置上 · 什么时候选它
FastAPI0.141.1Python 里做接口的默认选项。你要的是「一个窗口」
Flask3.1.3更老、更小、更自由的小框架。生态成熟,但校验和文档要自己配。适合喜欢「自己拼」的人
Django6.1.1整套后端方案。你要的是「一个带后台的网站」
Django REST Framework3.18.1给 Django 补上「做接口」的能力。已经用 Django 又需要接口时的常见选择
Litestar2.24.0同类新秀,思路和 FastAPI 接近。目前生态比 FastAPI 小得多,遇到问题可搜到的答案也少

10真上手之后才会知道的三件事

这一节的三件事,教程里通常不讲,但它们是「用起来之后」才会碰到的东西。

第一件:async def 还是 def——一条能让整个服务卡住的规则

先说结论,这是官方文档给的原话级规则:

🎯 官方给的判断法(照抄)

① 你调的库让你写 await(也就是它天生支持异步)→ 用 async def。
② 你调的库不支持 await(官方原文说,目前大多数数据库库就属于这种)→ 用普通的 def。
③ 你只是不知道 → 用普通的 def。

为什么这条规则值得你这种不写代码的人也记住?因为写错的代价不对称。

你写的FastAPI 实际怎么处理写错之后会发生什么
普通的 def官方原文:它会被放到一个「外部线程池」里执行再等结果,而不是直接调用——因为直接调用会阻塞服务器安全。它会替你兜底,代价是一点点开销
async def,但里面调了会「等」的老库直接被调用,运行在那条唯一的处理通道上整个服务会被这一个请求卡住,不只是卡住这一个请求——所有其他人的请求一起排队等

(上面提到的「外部线程池」,你可以理解成另开几个窗口同时办事;而 async 那条通道更像一个窗口靠不停切换来同时应付很多人——一旦有个人在窗口前站着不动,后面的人全堵住。)

⚠️ 对不写代码的你,这一条怎么落地

你不需要自己判断。你需要在验收时把这个问题原样问出去:

「这个 async def 里面,每一个调用都是原生支持 await 的库吗?只要有一个不是,就把它改回 def。」

然后观察 AI 的回答:如果它开始逐个列举「第一个是、第二个不是」,说明它真的想过;如果它直接回答「都是异步的,没问题」而没有任何列举,你就有理由要求它逐条列出来。这个问法之所以有效,是因为它有一个明确的、可以逐条核对的答案——这正是你缺的那种「可用依据」。

第二件:它省的是你的时间,不是你的服务器账单

「异步」这个词很容易让人得出一个推论:它更省资源,所以更省钱。真实情况比这复杂,有一个公开记录在案的例子。

🔍 一个真实的生产事故(BetterUp,2025-09-22 发布)

BetterUp 有一个叫 Lens 的内部服务:一个全异步的 FastAPI 服务,主要工作是查询多个数据源。他们写了这篇复盘,讲的是——部署了某个版本之后,进程占用的物理内存开始随时间线性爬升,把服务重新跑一遍(容器重启)才会降回去。

后果不是崩溃,而是账单:他们的自动扩容(机器不够用就自动加机器)是按内存使用量触发的(对一个几乎不吃 CPU 的服务,这个设置是合理的)。内存一路涨,扩容就一直加机器——他们观察到「流量并不高,却已经把机器加到上限」,在亚马逊云(AWS)上的开销被推高,而吞吐没有任何提升。

最后定位到根因不在业务代码,而在底层那些用别的语言写的组件(原生扩展)与内存分配器的行为,换用一个替代的内存分配器(jemalloc)后解决。

这个案例对你有两重价值:

💡 所以「更快」和「更省」是两笔账

FastAPI 的「快」主要在响应速度这一笔。资源消耗是另一笔账,它取决于你的代码怎么写、依赖了什么库、以及你跑在什么环境里。把这两笔账分开,是判断技术方案时一个很实用的习惯。

第三件:它动得快,所以别让版本把你带走

这是「活跃维护」的另一面。三个可核对的事实:

事实数字对你的意义
累计发布版本数317 个维护非常勤。这是优点
Python 3.8 的支持已被移除官方说明:装着 3.8 的机器只会装到 0.124.4,之后的新版它拒绝安装这是「活跃」的直接代价。官方专门说明这不是代码级破坏,而是「让你看见」的显式信号
Python 3.9 的支持也已被移除当前要求 3.10 以上连砍两个旧版本,说明它对 Python 版本的前进是跟着走的
它依赖的 Starlette本文校对当天(2026-09-23)刚发布 1.7.0底层组件几乎是天天在动

落到做法上只有两条:

# 1. 装的时候把版本写死,别用「最新版」
uv add "fastapi[standard]==0.141.1"

# 2. 隔一段时间主动升一次:把用到的包按清单升到允许的最新版
uv sync

如果你不直接操作命令,就把这句话写进给 AI 的任务卡里(§06 那份模板的第 7 条已经写了):「把版本号写死,并且每次改动前先告诉我你要动哪个包、从哪个版本到哪个版本。」——这样版本变动就从一个「悄悄发生的事」变成了一个你能看见的决定。

11一页纸:命令、地址、判断清单

命令速查

我要做的事命令什么时候用
检查 Python 版本够不够python3 --version动手第一步。低于 3.10 先别继续
装 uvbrew install uv 或 curl -LsSf https://astral.sh/uv/install.sh | sh没装过 uv 时
建项目uv init my-api && cd my-api开一个新接口服务
装 FastAPIuv add "fastapi[standard]"引号别省
装某个固定版本uv add "fastapi[standard]==0.141.1"不想被自动升级带走时
起本地服务(开发)uv run fastapi dev写代码时。会自动重启
起服务(上线)fastapi run部署时
关掉服务Ctrl + C终端被占住时
pip 路线(替代)python3 -m venv .venv → source .venv/bin/activate → pip install "fastapi[standard]"不用 uv 时。必须先建隔离环境

地址速查

地址是什么你什么时候会用到它
127.0.0.1:8000服务本身。只开在你自己这台机器上确认「跑起来了没」
/docs能点、能直接试的接口文档页验收 AI 成果;自己试接口;给前端交接
/redoc同一份内容,适合通读的排版要一次看完所有接口时
/openapi.json机器读的接口说明书让别的工具自动生成调用代码时

「该不该用」三问

🎯 拿这三句话去问你的项目

① 我要做的东西,是给程序调的(接口),还是给人看的(网页)?给程序调 → 它是默认选项;给人看 → 先看 Django。

② 我这个环境里有 Python 吗?谁维护它?没有、也没人维护 → 先解决这个,再谈框架。

③ 我要的是「一个窗口」,还是「一整套房子」?窗口 → 合适;房子 → 它只给你窗口那一块。

给 AI 的四句验收话

这四句是本文最可以直接抄走的东西——它们把「我看不懂代码」这个劣势,换成了「我问得出有明确答案的问题」这个优势:

1. 打开 /docs,把每个接口的地址、收什么、回什么,逐条念给我听。
2. 我故意传错一个字段的类型,你预计会返回什么?然后我们一起试一次。
3. 这个 async def 里的每个调用,都是原生支持 await 的库吗?有一个不是就改回 def。
4. 这次改动你动了哪些依赖、从哪个版本到哪个版本?请列出来。

12名词速查:见到它们时别当成什么用

这些词你在对接、看文档、问 AI 时都会撞见。第三列是本文认为最有用的一列——它告诉你这个词不该被当成什么。

术语一句话定义为什么重要 / 什么时候用 · 别当什么用
接口 / API两个程序之间约定好的交界口,就是餐厅的点单窗口它是一个口子,不是一整套系统。别把「做了个接口」理解成「做了个后端」
后端用户看不见的那一侧:接口、业务逻辑、数据存储接口只是它最外面一层。别把两者划等号,否则会低估工作量
框架已经搭好的骨架和规矩,你只填自己独有的部分它省的是「每道菜都要用的东西」。别当成熟练度——框架不会替你想业务
FastAPI用 Python 写接口的框架,靠类型标注自动做校验和文档默认选项,但有四条前提(§07)。别当成「后端全能选手」
Flask更老更小的 Python Web 框架自由度高、生态成熟。别以为「老 = 该淘汰」——它的稳定是优点
DjangoPython 的全套后端方案,自带后台管理与账号体系要建「带后台的网站」时选它。别拿下载量少就判它弱
Uvicorn一类「ASGI 服务器」程序里最常用的一个,负责收发网络请求它是最底下那层,比 FastAPI 快是必然的。别拿它俩的跑分直接比
Starlette负责「看地址决定交给哪段代码」的微框架FastAPI 建在它上面,所以不可能比它快。别把三层混成一层看
Pydantic负责按你声明的格式核对数据的库它是「门口核对订单」的那一环。别以为它管数据库
类型标注(type hints)写名字时顺手注明装的是文字还是数字FastAPI 三大好处的总开关。含糊的标注 = 三大好处一起失效
JSON一种固定写法的文本格式,机器读它、人也勉强能读接口之间最通用的「订单纸条」。别当编程语言
OpenAPI一份公开标准,规定「接口说明书该怎么写」正因为有它,那两页文档才是自动的、也才能被别的工具读。别当某个厂商的私有格式
Swagger UI / ReDoc把上面那份说明书渲染成网页的两个现成工具就是 /docs 和 /redoc。别当文档本身——文档是背后那份说明书
校验 / validation检查送进来的数据格式对不对在窗口做,不在仓库做。别把它当成数据库的数据约束,两者不互相替代
422一个约定俗成的编号:请求本身有问题看到 422 说明校验生效了;看到 500 说明是服务端出了没接住的错。别把这两者混为一谈
异步 / async、await「等的时候先干别的」的写法用不用取决于你调的库,不取决于想不想快。别当成「更快的开关」
线程池另开几个窗口同时办事FastAPI 用它兜住你写的普通 def。别以为写 def 就一定慢
路由「哪个地址交给哪段代码」这件事你写 @app.get("/") 就是在定义路由
ORM让你不用手写数据库语句就能操作数据的工具Django 自带,FastAPI 不带。别以为「不用 ORM」是缺点或优点,它只是不在这一层
PyPIPython 的官方软件仓库(也就是应用商店)下载量数据出自这里。别把下载量直接读成「最受欢迎」——它含自动构建与传递安装
虚拟环境 / .venv给一个项目单独隔离出来的 Python 环境用 pip 装包时必须先有它,否则会污染整台机器。细节见本仓的 虚拟环境

98来源与证据边界

这篇里凡是「现在是多少」「当前叫什么」「谁说的」的判断,都来自下面这些页面,核对日期统一为 2026-09-23。

官方文档与官方数据(一手)

独立来源(不是厂商自述)

本文自己做的核对(不是转述)

📖 证据边界与时效说明

时效:这篇属于「演进型」——机制与判断不容易过时,但版本号、下载量、依赖关系都在变。本文校对日期为 2026-09-23,所有版本号与下载量均为当日实测。用之前请以当期页面为准,尤其是 §10 那张版本表。

三处口径说明,避免你把数字读大:
① 下载量 ≠ 用户数。PyPI 的下载计数包含大量自动构建机器的重复拉取,以及「别的包依赖它、被顺带安装」的情况。本文只用它说明生态规模,不用它论证「它最适合你」。
② 「与 NodeJS 和 Go 相当」比的是框架层开销,不是你的应用跑起来的速度。本文在 §04 与 §09 各强调了一次,因为这是最容易被读歪的一句。
③ 200%–300%、40% 两处数字是厂商自测估计,官方脚注自己写明了来源。本文引用时同时给了脚注,不把估计当结论。

一处本文没有核实、因此没有展开的:官网与编辑器扩展里出现了官方的托管服务(FastAPI Cloud)与 2026-10-28 在阿姆斯特丹的 FastAPI Conf '26 入口。它们确实出现在官方页面横幅上,但本文没有去核实它的计费方式、能力边界与可用地区,所以正文里不作为选型依据出现——只知道「官方开始有托管入口了」即可,真要选它请自己查当期页面。

一个已知的说法分歧:关于「FastAPI 是不是最快的 Python 框架」,官方 benchmark 页的表述是「最快的之一,只低于 Starlette 和 Uvicorn 本身」(把三层放在一起排);而各类第三方对比文章常写成「FastAPI 就是最快的 Python 框架」,往往省略掉「只低于 Starlette 和 Uvicorn」这半句。本文取官方口径,并把三层的层级关系图放在 §04,供你自行判断。

99一句话总结

🎯 核心要点

FastAPI 是一个用 Python 写「接口」的框架:你用「注明类型」这一个动作,换回三件事——自动拦下格式填错的请求、自动生成不可能过期的接口文档、自动输出机器能读的标准说明书。

它值得「首选」这句话,但这句话的主语经常被省掉。完整版本是:在 Python 生态里,如果你的目标是给别人提供一个接口,它是目前的默认选项。你要自己核的是四条前提(用 Python、做接口、有人跟得上类型和依赖、能接受它更新快),以及三件上手后才会遇到的事(async def 的选择、异步服务可能「慢慢变贵」、版本要写死)。

对你这种不写代码、靠 AI 推进项目的角色,它最实在的价值其实是第四样:它给了你一个不需要读懂代码就能验收的界面(/docs)和四个有明确答案的问题(§11 末尾)。

留给你自己验的那一条

前面所有内容你都可以在文章里找到答案,只有这一条不行——它需要你自己的场景。请做一次:

拿你手上某个半途停下的项目,用 §11 的「该不该用三问」过一遍,然后写出你自己的那三行答案。例如:「我要做的是一个给自己用的数据看板,前端要读数据 → 这是接口,属于它的地盘;我这台电脑上有 Python 3.12,是之前学的时候装的 → 条件①成立;但我不需要后台管理,所以我要的确实只是一个窗口 → 条件②成立。」

如果你写完发现某一条卡住了(多半是「谁维护 Python 环境」这一条),那个卡住的地方就是你这个项目真正的下一个动作——而不是再读一篇框架介绍。

⌂