FastAPI 设计溯源:从 Django、Flask 到 Starlette 的替代方案、灵感来源与架构取舍全景解读
FastAPI 设计溯源从 Django、Flask 到 Starlette 的替代方案、灵感来源与架构取舍全景解读【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapiFastAPI并非凭空诞生它的每一个核心特性——基于 Python type hints 的校验、自动化的 OpenAPI 文档、依赖注入、高性能 ASGI 运行时——都能在它之前的十余个框架、库与工具中找到源头。本文以官方文档 docs/hi/docs/alternatives.md英文原文见 docs/en/docs/alternatives.md为主线逐一拆解 FastAPI 的前身工具谱系、它所借鉴的设计思想、以及它最终选择建立在Pydantic Starlette Uvicorn之上的底层原因并结合本仓库源码给出可验证的实现证据。引言为什么 FastAPI 会存在如果没有其他人此前的积累FastAPI就不会存在。在决定亲手造一个框架之前作者用了很多年时间回避这件事——他先是尝试用各种框架、插件和工具的组合去解决 FastAPI 如今覆盖的全部能力数据校验、序列化、自动文档、高性能、依赖注入……。直到某一天除了从过去工具中取最好的想法、用此前甚至不存在的语言能力Python 3.6 的 type hints把它们以最佳方式组合起来之外已经别无选择。理解这条从组合到自研的演进路径是理解 FastAPI 全部设计取舍的钥匙。下面按官方文档的顺序把这条路径上的每一个站点过一遍。一、此前工具的谱系FastAPI 借鉴了什么Django成熟全能框架的两面性Django 是最流行、被广泛信赖的 Python 框架曾被用来构建 Instagram 这类系统。但它与关系型数据库MySQL、PostgreSQL耦合较紧想用 NoSQL 数据库Couchbase、MongoDB、Cassandra 等作为主存储引擎并不容易。更重要的是定位差异Django 生来是在后端渲染 HTML而不是为现代前端React、Vue.js、Angular或 IoT 设备等外部系统提供 API。FastAPI从中看到的启示更多是反面教材——一个 Web 框架不必把 HTML 渲染、用户管理等能力全部内置。Django REST Framework自动 API 文档的启蒙者Django REST FrameworkDRF是在 Django 之上构建 Web API 的灵活工具包被 Mozilla、Red Hat、Eventbrite 等公司使用。它是自动 API 文档最早的示范之一也正是触发作者寻找 FastAPI的第一个想法。值得记住的一条人物线索DRF 由 Tom Christie 创建而 Starlette 与 Uvicorn 同样出自他手——这两者正是 FastAPI 的地基。FastAPI 借鉴点提供自动生成 API 文档的 Web 用户界面。Flask微框架哲学的直接继承者Flask 是microframework不带数据库集成也不带 Django 默认内置的众多功能。这种简洁与灵活性恰恰允许你用 NoSQL 当主存储同时它学习曲线平缓常用于那些并不真正需要数据库、用户管理等开箱即用特性的应用。文档明确指出部件解耦 可精确扩展的微框架是作者想要保留的关键特性。基于 Flask 的简洁它很适合构建 API于是下一步自然是寻找Flask 版的 Django REST Framework。FastAPI 借鉴点做一个微框架让所需工具与部件可以自由 mix and match拥有简单易用的路由系统。Requests客户端 API 风格反向塑造服务端 APIFastAPI 并不是 Requests 的替代品——两者作用域完全不同在 FastAPI 应用内部使用 Requests 反而是常见操作。Requests 是调用API客户端的库FastAPI 是构建API服务端的库分处互补的两端。Requests 的设计简单直观、默认值合理、开箱即用同时强大且可定制也因此成为有史以来下载量最高的 Python 包之一。看这两段代码的对称性response requests.get(http://example.com/some/url)app.get(/some/url) def read_url(): return {message: Hello World}requests.get(...)与app.get(...)的相似性并非巧合。在 FastAPI 源码中这些 HTTP 方法确实是直接以装饰器形式暴露在应用与路由上的例如 fastapi/routing.py 中api_route、get、post、put、delete等路径操作方法。FastAPI 借鉴点简洁直观的 API直接用 HTTP 方法名操作声明端点直白不绕弯有合理的默认值又保留强大的定制能力。Swagger / OpenAPI拥抱开放标准而非私有 Schema作者从 Django REST Framework 想拿走的核心能力是自动 API 文档。随后他发现业界已有用 JSON或 YAML描述 API 的标准Swagger且 Swagger 的 Web 用户界面早已存在——只要能生成 Swagger 文档就能自动套用这套 UI。后来 Swagger 被交给 Linux Foundation 并更名为OpenAPI因此聊 2.0 版本时习惯叫 Swagger3 版本则称 OpenAPI。FastAPI 借鉴点为 API 规范采用开放标准而非自定义 schema并集成基于标准的 UI 工具——Swagger UI与ReDoc。选择二者是因为足够流行与稳定事实上针对 OpenAPI 还有数十种其它界面可直接与 FastAPI 搭配使用。Flask REST frameworks放弃的原因市面上有多个 Flask REST 框架但作者投入时间调研后发现许多已经停止维护或被废弃且存在大量未解决的关键 issue因此无法胜任。Marshmallow用代码而非特设类定义 SchemaAPI 系统两个核心需求之一叫数据serialization序列化把 Python 对象比如来自数据库的数据、datetime对象转换成能走网络的形式。另一个核心需求是数据校验确认某字段确实是int而非任意字符串——这对外部传入数据尤其重要没有校验系统就得手写所有检查。Marshmallow 正是为这两点而生作者此前大量使用过它。但它诞生于 Python type hints 出现之前定义每个 schema 必须借助它提供的专属 utils 与 classes。FastAPI 借鉴点用代码定义 schemas让它自动提供数据类型与校验。这也直接解释了为何 FastAPI 选择 Pydantic——见下文第三部分。Webargs请求数据的自动解析与校验API 的另一个核心需求是从入站请求中parsing解析数据。Webargs 专门在 Flask 等多个框架之上提供这一点底层用 Marshmallow 做校验且出自同一批开发者。FastAPI 借鉴点对入站请求数据做自动校验。APISpec文档缺失的补课但引入了字符串内嵌语法问题Marshmallow 与 Webargs 以插件形式解决了校验、解析与序列化但文档仍缺失于是有了 APISpec。它同样是多框架含 Starlette的插件做法是在每个处理路由的函数 docstring 里用 YAML 书写 schema 定义再由它生成 OpenAPI schema。问题也随之而来YAML 是嵌在 Python 字符串里的微语法编辑器难以提供帮助一旦改了参数或 Marshmallow schema 却忘记同步改 docstring生成的 schema 就会过期。这是 FastAPI 明确要避免的陷阱——因此它坚持单一事实来源从同一份类型声明同时产出校验、序列化与文档。FastAPI 借鉴点支持 OpenAPI 这一 API 开放标准。Flask-apispec作者此前的心头好与它的上限Flask-apispec 把 Webargs、Marshmallow、APISpec 串成一个 Flask 插件用 Webargs/Marshmallow 的信息经由 APISpec 自动生成 OpenAPI schema解决了在 Python docstring 里手写 YAML的问题。作者评价它被严重低估并指出 Flask Flask-apispec Marshmallow Webargs 是他构建 FastAPI 前最喜欢的后端组合。这一组合还催生了多个 Flask full-stack generators而这些生成器后来正是FastAPI项目生成器对应文档 docs/en/docs/project-generation.md的前身。FastAPI 借鉴点从同一份定义序列化与校验的代码中自动生成 OpenAPI schema——这正是 FastAPI Pydantic 的核心机制。NestJS与 Angular编辑器支持与依赖注入的参照系NestJS 甚至不是 Python——它是受 Angular 启发的 JavaScript/TypeScript NodeJS 框架。它能做到与 Flask-apispec 类似的事情并拥有受 Angular 2 启发的内置依赖注入系统但要求预先注册 injectables带来一定的啰嗦与代码重复。参数用 TypeScript 类型描述让编辑器支持相当好可 TypeScript 类型在编译为 JavaScript 后不复存在无法仅靠类型同时定义校验、序列化与文档于是不得不在大量位置叠加装饰器代码相当冗长它对嵌套模型的处理也不佳——请求 JSON body 内部再有嵌套 JSON 对象时难以被正确文档化与校验。FastAPI 借鉴点用 Python 类型换取出色的编辑器支持拥有强大的依赖注入系统并想办法把代码重复降到最低。Sanic基于 asyncio 的高性能先驱Sanic 是最早一批基于asyncio的极速 Python 框架之一形态上刻意接近 Flask。技术细节在于它使用uvloop替代 Python 默认的asyncioloop——这正是它快的原因也启发了 Uvicorn 与 Starlette。FastAPI 借鉴点寻找获得惊人性能的路径。这正是 FastAPI 选择基于 Starlette 的原因——按第三方 benchmark 测试Starlette 是可用的最快框架。Falconrequest/response 双参数设计带来的局限Falcon 是另一个高性能 Python 框架设计上追求极简并作为 Hug 等框架的地基。它的函数接收两个参数——一个 request、一个 response从中读、写数据。这一设计决定了无法用标准 Python type hints 把请求参数与 body 声明为函数参数于是数据校验、序列化与文档只能在代码里手写或另建一层框架如 Hug来实现。FastAPI 借鉴点获得优秀性能的方法同时它与 HugHug 基于 Falcon共同启发了 FastAPI 在函数中声明response参数——在 FastAPI 中该参数是可选主要用于设置 headers、cookies 与替代状态码。Molten类型驱动思想的早期同路人作者在构建 FastAPI 初期发现了 Molten二者想法相当接近基于 Python type hints、由类型派生校验与文档、带依赖注入系统。差异在于Molten 不用 Pydantic 这类第三方校验库而是自带实现导致数据类型定义不易复用配置更冗长且基于 WSGI而非 ASGI无法享受 Uvicorn、Starlette、Sanic 提供的高性能依赖注入要求预注册且按声明类型解析无法为同一类型声明多个提供者路由集中在一处声明、调用别处定义的函数而非紧贴端点的装饰器更接近 Django 而不是 Flask/Starlette 的做法人为拆散了本应紧耦合的代码。FastAPI 借鉴点用模型属性的 default 值表达数据类型的额外校验——这改善了编辑器支持且当时 Pydantic 并不具备。该想法后来甚至反向推动了 Pydantic 更新如今这部分能力已全部内置于 Pydantic。Hugtype hints 声明参数的先行者Hug 是最早用 Python type hints 声明 API 参数类型的框架之一尽管它用的是自定义类型而非标准 Python 类型仍是巨大进步它也是最早为整个 API 生成 JSON 自定义 schema 的框架之一。不过它并不基于 OpenAPI / JSON Schema 这类标准与 Swagger UI 等工具集成并不直接。它还具备罕见的特性同一框架既能构建 API 也能构建 CLI。由于它基于 WSGI同步 Python Web 框架的旧标准无法处理 WebSocket 等场景尽管性能同样出色。人物注记Hug 由 Timothy Crosley 创建他同时也是isort的作者。FastAPI 借鉴点Hug 启发了 APIStar 的部分设计它推动 FastAPI 用 Python type hints 声明参数、自动生成定义 API 的 schema并在函数中声明response参数以设置 headers 与 cookies。APIStar 0.5FastAPI 的精神前身在决定构建 FastAPI 前不久作者发现了 APIStar server——它几乎具备他寻找的一切且设计出色是较早用 Python type hints 声明参数与请求的框架实现之一早于 NestJS 与 Molten并且采用了 OpenAPI 标准能基于同一套 type hints 做数据校验、序列化与 OpenAPI schema 生成。但 body schema 更接近 Marshmallow 风格编辑器支持不算最好。彼时 APIStar 的 benchmark 是最优的仅被 Starlette 超越最初没有自动文档 UI但作者清楚可以接入 Swagger UI它拥有依赖注入系统但同样要求预注册组件并且缺少 security 集成作者始终无法在完整项目中替换掉 Flask-apispec 全栈方案。随后项目焦点转移它不再是 API Web 框架作者需聚焦 Starlette今天 APIStar 是校验 OpenAPI 规范的工具集而非 Web 框架。人物注记APIStar 同样出自 Tom Christie——Django REST Framework、StarletteFastAPI 的底座、UvicornStarlette 与 FastAPI 的运行服务器的同一作者。FastAPI 借鉴点让它存在。用同一套 Python 类型同时声明数据校验、序列化与文档、且自带出色编辑器支持——这个想法是 FastAPI 的灵魂。APIStar 停更后Starlette 成为新的、更好的地基这也是构建 FastAPI 的最终灵感。作者将 FastAPI 视为 APIStar 的 spiritual successor在吸收上述所有工具经验的基础上改进并扩展了特性、类型体系与其余部件。二、FastAPI 脚下踩的三块基石如果说上一部分是曾经走过、最终舍弃的路这一部分则是 FastAPI 最终选择站在谁的肩膀上。Pydantic数据校验、序列化与 JSON SchemaPydantic 是基于 Python type hints 定义数据校验、序列化与文档JSON Schema的库因此极其直观。它与 Marshmallow 相当但 benchmark 中更快且因同样建立在 type hints 之上编辑器支持出色。FastAPI 用它处理全部数据校验、数据序列化与基于 JSON Schema 的模型自动文档化再把 JSON Schema 数据连同其它能力一起汇入 OpenAPI。仓库层面可以印证这一依赖在 pyproject.toml 中dependencies显式声明了pydantic2.9.0FastAPI 的所有请求/响应模型解析、校验错误处理均围绕 Pydantic 模型体系展开如 tests 目录中大量test_validate_response*.py、test_response_model*.py用例。StarletteASGI 微框架地基Starlette 是轻量级ASGI框架/工具包天生适合构建高性能 asyncio 服务设计上易于扩展、组件模块化。文档列出它的能力清单相当出色的性能WebSocket 支持进程内后台任务启动与关闭事件基于 HTTPX 的 TestClientCORS、GZip、Static Files、流式响应Session 与 Cookie 支持100% 测试覆盖率与 100% 类型注解代码库、依赖极少。Starlette 提供全部基础 Web 微框架功能但不提供自动数据校验、序列化或文档——这正是 FastAPI 叠加在其上的主要价值全部基于 type hints Pydantic外加依赖注入、安全工具、OpenAPI schema 生成等。技术细节ASGI 由 Django core team 成员推动发展虽尚未成为 Python 标准PEP但已被众多工具当作事实标准使用大幅提升了互操作性——例如可将 Uvicorn 换成 Daphne、Hypercorn 等任意 ASGI server或接入python-socketio等 ASGI 兼容工具。FastAPI 用 Starlette 处理全部核心 Web 部件并在其上叠加特性。代码层面可直接验证在 fastapi/applications.py 第 42 行class FastAPI(Starlette)——FastAPI 应用类直接继承自 Starlette。这意味着凡是 Starlette 能做的FastAPI 都能直接做它本质上就是加了料的 Starlette。Uvicorn闪电般的 ASGI 服务器Uvicorn 是基于 uvloop 与 httptools 构建的高速 ASGI server。它不是框架——例如不提供按路径路由的能力那由 Starlette或 FastAPI这类框架在上层提供。Uvicorn 是运行 Starlette 与 FastAPI 应用的推荐服务器也内置在仓库的依赖与 CLI 中pyproject.toml 的uvicorn[standard]依赖以及fastapi/cli.py、fastapi/__main__.py提供的命令行入口。FastAPI 将 Uvicorn 作为运行应用的主 Web server并可通过--workers命令行参数获得异步多进程能力。更多细节见 Deployment 部署章节。三、性能与基准三者关系如何理解Uvicorn、Starlette 与 FastAPI 三者的层级关系常被混淆Uvicorn 是 ASGI 服务器、Starlette 是 ASGI 框架/工具包、FastAPI 是在 Starlette 之上叠加数据校验与文档能力的应用框架。要理解、比较并看清三者的差异官方文档指向了专门的 Benchmarks 基准章节英文原版见 docs/en/docs/benchmarks.md。结合本文第一部分可以看到清晰的传承链Sanic 用 uvloop 证明Python 也可以极快→ 启发 Uvicorn 与 Starlette → 作者在考察了 Django REST Framework、Flask-apispec、APIStar 等一整套方案后最终选择基于 Starlette 加 Pydantic 的 FastAPI——用星标式的一句话概括即从过去的工具里取回正确的想法用 type hints 这一新语言能力把它们整合成单一、可自动化的栈。结语一份可复用的框架选型检查清单回看整个谱系FastAPI 对每个前身工具的关注点其实高度收敛可以归纳成一张评估Web API 框架的通用清单这也是阅读 docs/hi/docs/alternatives.md 最有价值的产出是否基于或兼容开放标准Swagger/OpenAPI 取代自定义 schema 是文档与工具生态打通的前提声明是否只有单一事实来源docstring 内嵌 YAMLAPISpec 路线必然面临改代码忘改文档的过期问题类型是否贯穿编译/运行期TypeScript 类型编译后消失导致 NestJS 需大量装饰器补偿Python type hints 在运行期保留得以同时驱动校验、序列化与文档运行时是否面向未来WSGI 系Molten、Hug难以覆盖 WebSocket 等高阶能力ASGI 系Starlette才有完整异步生态依赖注入是否零预注册预注册组件NestJS、Molten、APIStar带来代码重复FastAPI 用类型即契约的声明式方案规避性能是否经第三方验证从 Sanic 的 uvloop 到 Starlette性能是框架选型中可被 bench mark 实证的硬指标嵌套模型能否被正确文档化与校验这是 NestJS 等框架的短板也是 FastAPI 依托 Pydantic 递归模型能力的优势所在。最终FastAPI 选择站在Pydantic类型驱动的校验/序列化/JSON Schema StarletteASGI 微框架地基 UvicornASGI 服务器之上——正如仓库源码所证实的那样FastAPI类直接继承Starlettefastapi/applications.py而starlette与pydantic被列为最核心的运行时依赖pyproject.toml。理解了这条从 Django 一路延伸而来的灵感与替代脉络你也就理解了 FastAPI 为什么长成今天的样子。【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考