首页
/ FastAPI 框架的设计源流:灵感来源、同类框架横向对比与技术取舍全景解析

FastAPI 框架的设计源流:灵感来源、同类框架横向对比与技术取舍全景解析

2026-09-07 13:39:09作者:尤辰城Agatha

导读:本文围绕官方文档 Alternativas, Inspiración y Comparaciones(《备选方案、灵感来源与对比》)展开,系统梳理 FastAPI 诞生的技术背景、所借鉴的十余个历史框架与工具(Django、Flask、Requests、APIStar、Molten 等),深入剖析 FastAPI 直接采用并深依赖的 Pydantic、Starlette、Uvicorn 三者分工,并结合当前仓库源码(如 applications.pypyproject.toml)给出证据支撑。读完你将理解 FastAPI 的"为什么":它的类型驱动设计、自动文档、依赖注入、高性能路线分别继承自谁、舍弃了什么、又在哪里做出了关键性创新。

为什么需要了解 FastAPI 的"前世今生"

了解一个框架不能只看它的 API,还要看它解决的问题从何而来。官方文档用整章篇幅回顾了 FastAPI 的创作动机与灵感来源,核心观点可以概括为一句话:FastAPI 并不是凭空设计出来的全新事物,而是作者在多年尝试 Flask、Flask-apispec、Marshmallow、Webargs 等组合方案后,意识到"缺少一个把所有能力统一起来的框架",最终基于 Python 类型注解(type annotations)这一当时还相当新的语言特性,将前人最好的想法重新组合的产物。

在文档中,作者坦诚地写道:

FastAPI 不存在,如果没有其他人的工作。许多工具在此之前被创建,它们帮助启发了 FastAPI 的诞生。

具体而言,创作动因包括:

  • 作者曾多年回避"再造一个框架",而是试图用大量不同框架、插件与工具组合来覆盖最终 FastAPI 提供的能力;
  • 直到某一点,他意识到唯一的出路是创造一个新框架,把此前工具的最佳思想合并起来;
  • 而这一设想之所以到那时才可行,是因为 Python 3.6+ 提供了类型注解特性,让"一份代码同时声明类型、校验、序列化与文档"成为可能。

值得一提的是,原文档写作时代面向 Python 3.6+,而当前仓库 pyproject.tomlrequires-python = ">=3.10",且 docs_src 内的教程示例统一以 py310 命名,说明这一"用类型注解驱动一切"的设计理念随语言演进进一步强化——本仓库已是面向 Python 3.10+ 时代整理的文档与源码快照。

灵感来源:推动 FastAPI 走向成形的历史框架

原文将激励来源归纳为一条清晰的"谱系链",下面按原文脉络逐个梳理,并提炼每项工具给 FastAPI 带来的具体启示。

Django:最流行的"全家桶"及其边界

Django 是 Python 生态中最流行、最被广泛信赖的框架,作者指出它被用来构建 Instagram 这类大型系统。但它有两个结构性特点限制了它在作者当时场景下的适用性:

  1. 与关系型数据库(MySQL、PostgreSQL 等)耦合较深,如果想把 NoSQL(Couchbase、MongoDB、Cassandra 等)作为主存储引擎,会相当不顺手;
  2. 它最初的设计目标是在服务端生成 HTML,而不是面向现代前端(React、Vue.js、Angular)或 IoT 设备提供 API 数据。

这两点正是"API 优先"框架要解决的核心场景。原文据此给出的启示并不在于模仿 Django,而在于明确了一个反面边界:FastAPI 不必把服务器渲染、ORM 全家桶都内置进来。

Django REST Framework:自动 API 文档的启蒙者

Django REST Framework(DRF)是建立在 Django 之上的 Web API 工具包,被 Mozilla、Red Hat、Eventbrite 等公司使用。它对 FastAPI 最重要的意义,是最早让作者意识到"API 自动文档"可以成为一个框架的内建能力——这也是 FastAPI 追求的目标之一。

它是 API 自动文档的首批示例之一,而这一点正是最初启发作者"寻找" FastAPI 的想法之一。

原文特别注明了一个关键人物关系:DRF 由 Tom Christie 创建,他同时也是 Starlette 与 Uvicorn 的创造者,而这两者正是 FastAPI 的地基。 这条人物线贯穿了 Django REST Framework → APIStar → Starlette → Uvicorn → FastAPI 的完整谱系。

Flask:微框架哲学与"只取所需"的自由

Flask 是"微框架"(microframework),默认不捆绑数据库集成与 Django 自带的大量功能。这份简单与灵活使它能够支持 NoSQL 等非默认存储方案,学习曲线相对友好。作者尤其看重它的两点特质并希望 FastAPI 保留:

  • 微框架的"可拼装"哲学:需要什么就加什么,各部分相互解耦;
  • 简单直观的路由系统

文档写道,基于 Flask 的简洁性,它看起来非常适合用来构建 API,于是作者的下一步是寻找"Flask 版的 Django REST Framework"——这直接引出了下文的一批 Flask REST 生态工具。需要指出,FastAPI 团队也延续了这套哲学:核心依赖极少(见 pyproject.toml,仅 starlette、pydantic、typing-extensions、typing-inspection、annotated-doc 五项),而表单、模板、测试客户端、邮箱校验等能力全部通过 standard 附加依赖(optional-dependencies)按需安装。

Requests:极简 API 设计范本(客户端视角)

Requests 是 Python 中与 API 打交道的 HTTP 客户端库,而 FastAPI 是构建 API 的服务端框架,二者本不构成"替代"关系,甚至常常搭配使用——在 FastAPI 应用内部用 Requests 去调用别的服务非常常见。但 FastAPI 从 Requests 身上学到了大量 API 设计语言:

  • API 要简单直观
  • 直接用 HTTP 方法名(operation)作为函数入口,例如 GET 就对应 requests.get
  • 提供合理默认值,同时保留强大定制能力。

原文用一段极富说服力的对照代码展示这份"对称性"——客户端发起 GET 请求:

response = requests.get("http://example.com/some/url")

与之对应的 FastAPI path operation(服务端接收该请求)写法是:

@app.get("/some/url")
def read_url():
    return {"message": "Hello World"}

requests.get(...)@app.get(...) 的相似并非巧合,而是有意的设计传承。在仓库中,这套以 HTTP 动词命名的方法实现在 routing.pyAPIRouter 类中:getpostputdeletepatchoptionshead 等装饰器方法一应俱全(约 routing.py 起依次定义),而 FastAPI 应用对象本身复用同一套 APIRouter。此外 Requests 官网自称"有史以来被下载最多的 Python 包之一"——原文引用这一说法,意在说明"简单直观"的 API 设计能带来多广的接受度。

Swagger / OpenAPI:从私有 schema 走向开放标准

作者从 DRF 获得的最大愿望是 API 自动文档,随后发现业界已有描述 API 的开放标准——Swagger(以 JSON 或其超集 YAML 描述 API),并且已经有基于 Swagger 的 Web UI。只要能输出 Swagger 规格,就能直接套用现成的交互式文档界面。

后来 Swagger 被移交给 Linux Foundation 并更名 OpenAPI:一般 2.0 时代称 "Swagger",3.x 起称 "OpenAPI"。FastAPI 由此得到两个明确启示:

  • 采用开放的 API 标准,而不是自造私有 schema;
  • 对接基于标准的文档 UI 工具:Swagger UI 与 ReDoc(文档提到二者因流行且稳定被选中,而 OpenAPI 生态中还有大量同类 UI 可选)。

这一设计在当前仓库中有非常直接的落地证据:FastAPI 启动时会自动挂载 /openapi.json/docs(Swagger UI)与 /redoc(ReDoc)三条路由,见 applications.py,且三个 URL 均可通过构造参数 openapi_urldocs_urlredoc_url 定制(例如 FastAPI(docs_url="/documentation", redoc_url=None),见 applications.py 的文档字符串示例)。生成的 OpenAPI schema 默认版本为 3.1.0,见 openapi/utils.py

Flask REST 生态的困境:Flask-apispec 组合的成败

作者调研了多个 Flask REST 框架,发现许多已停止维护或不适合生产;而随后登场的一组"黄金组合"则构成了他构建 FastAPI 之前最钟爱的后端技术栈:Flask + Flask-apispec + Marshmallow + Webargs。逐一看它们各解决什么问题:

工具 解决的问题 FastAPI 的继承方式
Marshmallow 数据序列化(把 datetime、ORM 对象等转成可传输的 JSON)与数据校验(确保字段是 int 而不是任意字符串等) 用 Python 代码定义"schemas",自动获得类型与校验。但它诞生于 Python 类型注解出现之前,需借助专用类与工具定义 schema
Webargs 解析入站请求数据(由 Marshmallow 提供底层校验),由同一批作者开发 对入站请求数据的自动校验
APISpec 在函数 docstring 里用 YAML 微语法写 schema 定义,据此生成 OpenAPI 支持开放标准 OpenAPI
Flask-apispec 把上述三者串起来:用 Webargs/Marshmallow 信息自动生成 OpenAPI,免去手写 YAML 从"定义序列化与校验的同一份代码"自动生成 OpenAPI schema

这套组合解决了"手写 YAML"的问题,却仍留下结构性痛点——docstring 里的 YAML 是字符串中的微语法:编辑器几乎无法提供帮助;一旦改了 Marshmallow 参数或 schema 而忘记同步 YAML,生成出的文档就会失真过期。Flask-apispec 本身被作者评价为"非常被低估的好工具",其文档过于简洁抽象可能是它不够流行的原因。

这些基于 Flask 的 full-stack 项目生成器后来直接成为 FastAPI 项目生成器(Project Generators)的基础,见 project-generation.md

NestJS 与 Angular:TypeScript 世界的镜鉴

NestJS 是受 Angular 启发的 Node.js/TypeScript 框架,并非 Python 工具,但它实现了与 Flask-apispec 类似的目标。作者从 NestJS(及其背后的 Angular 依赖注入)观察到了三个反面教材式的问题:

  1. DI 系统需要预先注册"可注入项",带来额外冗余与重复代码;
  2. TypeScript 的类型信息在编译成 JavaScript 后不保留,因此无法像 Python 运行时类型那样"一份类型同时用于校验、序列化与文档",只能靠到处写装饰器补救,导致冗长;
  3. 嵌套模型处理不佳——当请求 JSON body 的字段本身是嵌套 JSON 对象时,难以被正确文档化与校验。

与之相对的正面收获则是:使用带类型的语言/注解能带来优秀的编辑器支持,以及"强大的依赖注入 + 最小化代码重复"的追求。有趣的是,FastAPI 之所以能在 Python 上达成"运行时保留类型"的效果,正是因为 Python 的类型注解会在运行时真实可查,再由 Pydantic 把这些注解转化为校验与 JSON Schema 能力。

Sanic:asyncio 高并发路线的最早探路者

Sanic 是 Python 最早基于 asyncio 的超高速框架之一,API 形态刻意贴近 Flask。文档的"技术细节"注明:它使用 uvloop 替代 Python 默认的 asyncio event loop,这是它速度的来源,也直接启发了 Uvicorn 与 Starlette(作者称二者在公开基准测试中已快于 Sanic)。

Sanic 给 FastAPI 的启示是追求惊艳的性能;而 FastAPI 之所以选择建立在 Starlette 之上,正是因为作者认为(依据第三方基准测试)它是当时可用的最快框架。

Falcon:request/response 对象范式与 Hug

Falcon 是另一个 Python 高性能框架,设计上走极简路线,作为 Hug 等上层框架的底座。它的核心风格是处理函数接收两个参数 requestresponse,然后从 request "读"、向 response "写"。这种设计的代价是:无法用标准 Python 类型注解把请求参数和 body 声明为函数参数,于是校验、序列化、文档只能手写或由上层框架(如 Hug)补齐。

FastAPI 从 Falcon + Hug 中收获的灵感颇具戏剧性——采纳"在函数中声明一个 response 参数"这一想法,但在 FastAPI 里它被做成可选参数,主要用于设置响应 headers、cookies 或替代性状态码,而不是强制性的读写对象。仓库中关于 response 参数的这一可选用法,可对照 response 相关教程与 Response 注入机制查看(如 docs_src/response_change_status_codedocs_src/response_headers)。

Molten:理念最接近的"同行"

Molten 是作者在 FastAPI 早期就发现的框架,两者理念惊人相似:

  • 都基于 Python 类型注解;
  • 都从这些类型推导校验与文档;
  • 都内置依赖注入(DI)。

但作者梳理出 Molten 的几处差异与局限:

  • 不用 Pydantic 这类第三方校验/序列化/文档包,而是自带一套类型系统,导致数据类型定义不易复用;
  • 配置相对冗长,且基于 WSGI 而非 ASGI,无法享受 Uvicorn、Starlette、Sanic 所代表的高性能异步路线;
  • DI 需要预先注册依赖,且按声明类型解析依赖,同一个类型无法注册多个"组件"
  • 路由集中在一处声明,再引用别处定义的函数(更接近 Django 而非 Flask/Starlette 的装饰器紧贴处理函数风格),把相对内聚的代码拆散了。

Molten 反过来给 FastAPI(乃至 Pydantic)贡献了一个具体技巧:用模型属性的"默认值"(default)声明额外校验,这能显著改善编辑器体验,而当时的 Pydantic 尚不支持这种写法——这一思想最终推动了 Pydantic 相应能力的更新。Pydantic 生态当前的校验声明方式(Field 上的默认值约束、校验器等)正是这一历史对话的产物。

Hug:API + CLI 二合一的天才构想

Hug 是首批用 Python 类型注解声明 API 参数类型的框架之一,作者称之为"伟大突破"。它同时是首批用 JSON 声明并自动生成(私有)API schema 的框架。它的局限在于:schema 并非基于 OpenAPI/JSON Schema 开放标准,因此难以直接对接 Swagger UI 等生态工具。

Hug 还有一个少见的特色——用同一套代码既能构建 API 也能构建 CLI。由于基于同步 WSGI 标准,它无法处理 WebSocket 等异步能力(即便如此性能仍很高)。值得一提的花絮:Hug 由 Timothy Crosley 创建,他同时也是 isort(Python import 自动排序工具)的作者。

Hug 对 FastAPI 的启发清单在原文中非常明确:

  • 用 Python 类型注解声明参数;
  • 自动生成描述 API 的 schema;
  • 支持在函数中声明 response 参数,用于设置 headers 与 cookies。

APIStar(<= 0.5):FastAPI 的"精神前任"

APIStar 是压垮作者"再造轮子"心理防线的最后一根稻草。在决定构建 FastAPI 之前,作者发现 APIStar server 几乎具备他想要的一切:

  • 最早用 Python 类型注解声明参数与请求的框架实现之一(早于 NestJS 与 Molten,作者大约同时期发现它与 Hug);
  • 基于 OpenAPI 开放标准
  • 用同一批类型注解自动完成数据校验、序列化与 OpenAPI schema 生成;
  • 当时基准测试成绩最佳(仅次于 Starlette);
  • 内置依赖注入系统(虽然仍需预先注册组件)。

APIStar 的 body schema 定义并非标准 Python 类型(更接近 Marshmallow 风格),编辑器支持不够好,且当时缺少安全集成,使作者无法在完整项目中替换掉基于 Flask-apispec 的 full-stack 方案——他甚至计划为它提交 PR 补上安全能力。但随后项目方向剧变:其创建者转向专注 Starlette,APIStar 不再作为 Web 框架存在,如今只是校验 OpenAPI 规范的工具集,不再是服务器框架。

原文的"注释"再次点明人物线索:APIStar 同样出自 Tom Christie 之手——他同时创造了 Django REST Framework、Starlette(FastAPI 的地基)与 Uvicorn(Starlette 与 FastAPI 实际使用的服务器)。

正是 APIStar 的谢幕促成了 FastAPI 的诞生:APIStar 消失后,Starlette 成为更好、更新的地基,作者由此获得最终灵感,并明确表态:

我认为 FastAPI 是 APIStar 的"精神继任者"(spiritual successor),在其基础上改进并扩展了功能、类型系统与其他部分,同时吸收了所有这些早期工具的经验教训。

FastAPI 直接采用并深度依赖的三大组件

如果说上一节讲的是"灵感来源",这一节则是"直接地基"——FastAPI 不是从零实现一切,而是明确站在三个成熟组件的肩膀上,只负责把它们的缝隙补上。原文分别阐述了三者与 FastAPI 的分工。

Pydantic:数据校验、序列化与 JSON Schema

Pydantic 是一个基于 Python 类型注解定义数据校验、序列化与文档(JSON Schema)的包。文档认为它与 Marshmallow 定位可比,但基于同一套 Python 类型注解使其编辑器支持远胜,且(文档称)在基准测试中更快。

FastAPI 用它来做:处理全部数据校验、数据序列化与基于 JSON Schema 的模型自动文档;FastAPI 再把生成的 JSON Schema 汇入 OpenAPI,完成其余所有工作。

当前仓库对这份依赖给出了精确版本证据:pyproject.toml 声明 "pydantic>=2.9.0",且仓库包含 Pydantic v1 兼容教程(docs_src/pydantic_v1_in_v2)与大量 v2 兼容测试(如 tests/test_schema_compat_pydantic_v2.py),印证 Pydantic 在 FastAPI 中扮演的正是"类型 → 校验 → 文档"转换中枢。

Starlette:全部 Web 基础设施

Starlette 是轻量级 ASGI framework/toolkit,专为构建高性能 asyncio 服务而生。文档罗列了它自带的能力清单:

  • 惊人的性能;
  • WebSocket 支持;
  • 进程内后台任务;
  • 启动/关闭事件(lifespan);
  • 基于 HTTPX 的测试客户端;
  • CORS、GZip、静态文件、流式响应;
  • 会话与 Cookie 支持;
  • 100% 测试覆盖率;
  • 100% 类型注解的代码库;
  • 极少的强制依赖。

Starlette 提供了微框架应有的全部 Web 底层能力,但不提供自动数据校验、序列化或文档——这正是 FastAPI 在其上叠加的核心增量:类型驱动的校验/序列化、依赖注入系统、安全工具(security utils)、OpenAPI schema 生成等。

这一"继承关系"在当前仓库中是字面意义的代码事实:查看 applications.py 可以看到:

class FastAPI(Starlette):

也就是说 FastAPI 类直接继承自 Starlette 的 Starlette 类——原文"你能用 Starlette 做的任何事都能直接在 FastAPI 上做,因为它本质上是被增强的 Starlette"这一论断,可由源码逐字验证。

文档中的"技术细节"还解释了 ASGI 标准的当时状态:ASGI 是 Django 核心团队成员正在推动的新标准,当时还不是 Python 正式标准(PEP),但已被大量工具当作事实标准使用。其互操作性红利在于:可以随时把 Uvicorn 换成其他 ASGI 服务器(如 Daphne 或 Hypercorn),或接入 python-socketio 等 ASGI 兼容工具。

Uvicorn:ASGI 服务器与 --workers

Uvicorn 是基于 uvloop 与 httptools 构建的极速 ASGI 服务器。它不是 Web 框架——例如它不提供路径路由能力,那是 Starlette/FastAPI 这类框架在其上层提供的。

FastAPI 将它作为:运行 FastAPI 应用的主 Web 服务器;也可用命令行参数 --workers 启动多进程异步服务器。

更多部署细节见官方 Deployment 文档。这也再次印证了 FastAPI 生态的分层哲学:服务器(Uvicorn)、Web 工具层(Starlette)、应用框架(FastAPI)、数据层(Pydantic)各司其职,均可独立替换。

性能主张应当如何理解

文档在结尾明确提醒:要理解 Uvicorn、Starlette 与 FastAPI 三者之间的差异,应去阅读 Benchmarks(基准测试)章节,仓库对应基准脚本可见 tests/benchmarks

关于性能,文档给出的判断带有明确的作者视角与时点背景:作者认为 Starlette 是当时公开基准测试中最快的 Python 框架,其上方只有 Uvicorn——而 Uvicorn 本质是服务器而非框架;Sanic 的 uvloop 路线启发了 Uvicorn 与 Starlette,而后者在开放基准中已超越 Sanic。需要提醒的是:基准测试结果高度依赖场景、版本与硬件,这类"最快"表述属于文档作者基于彼时第三方基准的个人判断,不应被当作无条件成立的绝对事实。当前仓库自身也并未在 pyproject.toml 或其他配置中声明任何官方性能数字。

谱系图式的总结:一条可复用的技术判断框架

把全文线索收束起来,FastAPI 的设计取舍可以归纳为四条贯穿性的判断标准,任何想评估新框架的开发者都可以照此提问:

  1. 类型是否能"一份多用"? 是否能用一份 Python 类型注解同时驱动参数解析、数据校验、序列化与 OpenAPI 文档,避免 Marshmallow/YAML docstring 时代的"多处定义、易失同步"问题?(对照 Marshmallow、APISpec、NestJS 的反面经验)
  2. 是否站在开放标准上? 是否采用 OpenAPI/JSON Schema,从而直接接入 Swagger UI、ReDoc 等现成生态?(对照 Hug 私有 schema 的教训)
  3. 性能路线是否现代化? 是否基于 ASGI 而非 WSGI,能否利用 Uvicorn/Starlette 一系的异步高性能?(对照 Molten、Falcon 的 WSGI 局限)
  4. 是否追求微框架式的可拼装与低重复? 核心依赖精简、装饰器紧贴处理函数、DI 无需预注册、冗余降到最低?(对照 Django 的厚重、NestJS 的冗长与 APIStar/Molten 的预注册 DI)

而 FastAPI 之所以能被作者称为 APIStar 的"精神继任者",正在于它把上述所有正面答案集中在同一个类型系统之上,再以"站在 Starlette 之上"的方式继承了完整的 Web 能力。想进一步了解 FastAPI 在创作之后的设计演化与未来设想,可以继续阅读配套文档 history-design-future.md;想回顾 FastAPI 相对这些工具的全部能力亮点,可阅读 features.md

登录后查看全文
热门项目推荐
相关项目推荐