Starlette 应用类Starlette完全指南从路由、生命周期到状态管理的核心用法【免费下载链接】starletteThe little ASGI framework that shines. 项目地址: https://gitcode.com/gh_mirrors/st/starletteStarlette 框架的核心是一个名为Starlette的应用类Application Class它负责把路由routing、中间件middleware、生命周期管理lifespan、静态文件与异常处理等所有子模块编织成一个完整的 ASGI 应用。本文基于本仓库的官方文档 docs/applications.md 与源码实现 starlette/applications.py带你掌握如何实例化一个 Starlette 应用、配置路由与中间件、通过app.state存储共享状态以及如何在端点中通过request.app反向访问应用实例——读完即可编写出结构完整、可上线的 Starlette 应用。什么是 Starlette 应用类Starlette 的定位是小而美的 ASGI 框架而Starlette应用类正是把所有零散能力HTTP 路由、WebSocket 路由、子应用挂载、静态文件、生命周期钩子、异常处理、中间件栈统一组织起来的总装配线。从源码看starlette/applications.py 中Starlette.__init__只做几件事保存debug调试开关创建self.state State()用于存储任意应用级状态用Router(routes, lifespanlifespan)创建内部路由器负责所有请求分发保存exception_handlers、user_middleware与max_body_size初始化self.middleware_stack None直到第一次被调用__call__时才惰性构建中间件栈。这意味着你创建app Starlette(...)时得到的其实是一个符合 ASGI 规范的 callable 对象任何支持 ASGI 的服务器如 uvicorn都可以直接运行它。一个完整的应用示例官方文档给出了一个几乎覆盖全部核心特性的示例它同时演示了普通路由、路径参数、WebSocket 路由、子应用挂载静态文件与 lifespan 生命周期from contextlib import asynccontextmanager from starlette.applications import Starlette from starlette.responses import PlainTextResponse from starlette.routing import Route, Mount, WebSocketRoute from starlette.staticfiles import StaticFiles def homepage(request): return PlainTextResponse(Hello, world!) def user_me(request): username John Doe return PlainTextResponse(Hello, %s! % username) def user(request): username request.path_params[username] return PlainTextResponse(Hello, %s! % username) async def websocket_endpoint(websocket): await websocket.accept() await websocket.send_text(Hello, websocket!) await websocket.close() asynccontextmanager async def lifespan(app): print(Startup) yield print(Shutdown) routes [ Route(/, homepage), Route(/user/me, user_me), Route(/user/{username}, user), WebSocketRoute(/ws, websocket_endpoint), Mount(/static, StaticFiles(directorystatic)), ] app Starlette(debugTrue, routesroutes, lifespanlifespan)要点拆解Route(/user/{username}, user)是带路径参数的路由{username}会作为路径参数注入端点函数内通过request.path_params[username]读取WebSocketRoute(/ws, ...)处理 WebSocket 连接端点函数接收websocket对象而非request需要手动执行accept()/send_text()/close()三件套Mount(/static, StaticFiles(directorystatic))把静态文件子应用挂载到/static前缀下StaticFiles 本身也是一个独立 ASGI 应用lifespan是asynccontextmanager装饰的异步上下文管理器yield之前为启动Startup阶段yield之后为关闭Shutdown阶段。运行该应用最常用的方式是 uvicorn本仓库未内置服务器需配合外部 ASGI 服务器# 假设上述代码保存在 app.py模块内存在全局变量 app uvicorn app:app --reload深入构造函数六大参数详解Starlette.__init__的完整签名如下见 starlette/applications.pydef __init__( self, debug: bool False, routes: Sequence[BaseRoute] | None None, middleware: Sequence[Middleware] | None None, exception_handlers: Mapping[Any, ExceptionHandler] | None None, lifespan: Lifespan[AppType] | None None, *, max_body_size: int | None None, ) - None参数类型默认值作用debugboolFalse出错时是否返回带完整调用栈的调试回溯信息tracebackroutesSequence[BaseRoute]None接收 HTTP / WebSocket 请求的路由列表middlewareSequence[Middleware]None每个请求都会经过的中间件列表exception_handlersMappingNone状态码或异常类型到处理函数的映射lifespanLifespanNone启动/关闭钩子的异步上下文管理器max_body_sizeint \| NoneNone请求体最大字节数None表示不限制以下逐一结合源码说明debug开启后未被捕获的异常会返回包含完整堆栈的调试页面关闭时则返回通用的 500 错误响应。debug值会被传递给自动装配的ServerErrorMiddleware与ExceptionMiddleware见下文中间件栈一节。测试用例 tests/test_applications.py 验证了app.debug True时响应正文中会包含RuntimeError的异常信息。routes路由列表中的每一项都是BaseRoute的实例最常用的四种在 starlette/routing.py 中定义Route(path, endpoint)HTTP 路由端点函数签名形如def endpoint(request) - Response可同步也可异步WebSocketRoute(path, endpoint)WebSocket 路由端点签名形如async def endpoint(websocket)Mount(path, app)挂载子应用如StaticFiles、另一个Router或另一个Starlette实现模块化拆分Host(host, app)按主机名支持{subdomain}路径参数分发请求测试用例 tests/test_applications.py 演示了Host({subdomain}.example.org, appsubdomain)的用法。路由列表也可以通过app.router.routes或app.routes属性在运行期读取starlette/applications.py。middleware在构造时通过middleware[Middleware(Cls, **kwargs), ...]传入。注意Middleware是一个包装类见 starlette/middleware/init.py它不直接实例化中间件而是延迟保存cls / args / kwargs等构建中间件栈时才真正实例化——这保证了中间件只被创建一次。此外也可以调用app.add_middleware(Cls, *args, **kwargs)动态追加见下文。exception_handlers映射的键可以是整数状态码如404、500、405或异常类如HTTPException值是对应的处理函数签名形如handler(request, exc) - Response同步/异步皆可。源码 starlette/applications.py 在构建栈时会做特殊分流键为500或Exception的处理函数会被升级为最外层ServerErrorMiddleware的处理器其余交给内层ExceptionMiddleware。测试用例 tests/test_applications.py 展示了 500 / 405 /HTTPException三种处理器的写法其中 405 处理器自定义了Method Not Allowed的响应内容。lifespan生命周期上下文管理器yield之前执行启动任务如初始化数据库连接池、加载缓存yield之后执行关闭任务如释放资源、关闭连接。更完整的说明见下方生命周期管理小节。max_body_size请求体大小上限字节。传入非None值时会自动在中间件栈中加入RequestBodyLimitMiddleware见 starlette/middleware/body_limit.py超过限制的请求会被拒绝。这也是保护服务免受超大请求体攻击的简单手段。中间件栈是如何构建的Starlette的中间件栈采用惰性构建策略在__call__即应用真正收到 ASGI 请求时才调用build_middleware_stack()见 starlette/applications.py其执行逻辑为从exception_handlers中分离出 500 /Exception处理器作为error_handler依次组装最外层ServerErrorMiddleware兜底任何未被捕获的异常是整条栈的安全网若设置了max_body_sizeRequestBodyLimitMiddleware用户通过middleware或add_middleware()传入的中间件最内层ExceptionMiddleware处理路由与端点中已注册的异常用reversed(middleware)从内向外逐层包裹self.router最终形成完整的 ASGI 调用链。也就是说即使你不传任何中间件每个 Starlette 应用也始终自动包含这两个内置中间件——这是源码中明确的行为starlette/applications.py。文档中的对应表述是ServerErrorMiddleware作为最外层处理整个调用栈中的未捕获错误ExceptionMiddleware作为最内层处理路由和端点中的受控异常。测试用例 tests/test_applications.py 验证了中间件栈的惰性构建同一个应用实例多次服务请求中间件构造函数的计数器始终保持为 1。生命周期管理LifespanStarlette 应用通过 ASGI 的lifespan协议消息与服务器协调启动/关闭。Router.lifespan方法的实现starlette/routing.py揭示了底层机制服务器发送lifespan.startup消息后应用进入self.lifespan_context(app)异步上下文正常则回复lifespan.startup.complete若启动失败则回复lifespan.startup.failed关闭阶段失败则回复lifespan.shutdown.failedlifespan 还可以产出状态yield {key: value}时若服务器支持scope 中存在state产出内容会被合并进scope[state]随后通过request.state在每个请求中访问。测试 tests/test_applications.py 展示了yield {count: 1}后端点通过request.state[count]读取的应用场景。官方推荐的 lifespan 写法是contextlib.asynccontextmanager装饰的异步生成器函数源码同时兼容旧的裸 async 生成器函数与同步生成器函数写法但会抛出StarletteDeprecationWarning弃用警告starlette/routing.py新代码应统一使用asynccontextmanager风格。在应用实例上存储状态app.state官方文档明确支持在应用实例上保存任意自定义状态方式是通过通用的app.state属性app.state.ADMIN_EMAIL adminexample.orgapp.state是State类的实例starlette/datastructures.py它对使用者完全透明地代理到底层字典上同时支持两种访问风格# 属性风格 app.state.ADMIN_EMAIL adminexample.org print(app.state.ADMIN_EMAIL) # 字典风格 app.state[ADMIN_EMAIL] adminexample.org print(app.state[ADMIN_EMAIL])此外State还实现了__delattr__删除、__iter__迭代所有键与__len__统计条目数。读取不存在的属性会抛出AttributeError。它同时被用于app.state应用级、全局共享与request.state请求级、单请求作用域——两者是同一个类只是作用范围不同。访问应用实例request.app在任意端点或中间件中只要拿到了request对象就可以通过request.app访问当前 Starlette 应用实例def homepage(request): return PlainTextResponse(Hello, %s! % request.app.state.ADMIN_EMAIL)其底层实现非常直接starlette/requests.pyStarlette.__call__在处理任何请求前都会执行scope[app] selfstarlette/applications.py把自身写入 ASGI scope而Request.app属性就是self.scope[app]的一行返回。这为端点内反查应用配置如读取app.state中的全局设置、调用app.url_path_for提供了标准入口。实用方法速查Starlette类还提供了一批便捷方法可直接在应用实例上调用见 starlette/applications.py方法作用app.routes返回当前路由列表属性app.url_path_for(name, **path_params)按路由 name 反解出完整 URL 路径如app.url_path_for(user, usernametom)得到/user/tom未找到时抛NoMatchFoundapp.mount(path, app, nameNone)等价于在路由列表追加Mount如app.mount(/static, StaticFiles(...))app.host(host, app, nameNone)等价于追加Host路由按主机名分发app.add_middleware(cls, *args, **kwargs)运行时追加中间件插到用户中间件列表最前应用已启动后调用会抛RuntimeErrorapp.add_exception_handler(exc_class_or_status_code, handler)运行时注册异常/状态码处理器app.add_route(path, route, methodsNone, nameNone, include_in_schemaTrue)运行时追加 HTTP 路由其中url_path_for在 tests/test_applications.py 中有直接验证app.url_path_for(func_homepage) /func。add_middleware的内部实现是把新中间件插入user_middleware的头部starlette/applications.py并配合启动后禁止追加的保护逻辑避免运行期栈结构不一致。如何验证你的应用本仓库提供了完整的测试套件可供参考tests/test_applications.py覆盖了普通/异步/类视图路由test_func_route、test_async_route、test_class_route、子应用挂载test_mounted_route、WebSocket 路由与异常关闭、自定义 404/405/500 处理器、中间件参数传递、lifespan 启动关闭时序、以及app.state/request.state的共享状态传递。你可以在本地安装依赖后运行pytest tests/test_applications.py -v在开发调试阶段则可以用TestClient直接对应用实例发起模拟请求见 docs/testclient.md无需启动真实服务器即可验证路由、中间件与生命周期逻辑。延伸阅读starlette/applications.pyStarlette类完整源码starlette/routing.pyRouter、Route、WebSocketRoute、Mount、Host的定义starlette/datastructures.pyState状态容器实现starlette/middleware/init.pyMiddleware延迟实例化包装类tests/test_applications.py应用层功能测试仓库其他官方指南docs/routing.md路由详解、docs/middleware.md中间件、docs/lifespan.md生命周期、docs/requests.md请求对象、docs/responses.md响应对象、docs/staticfiles.md静态文件。【免费下载链接】starletteThe little ASGI framework that shines. 项目地址: https://gitcode.com/gh_mirrors/st/starlette创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
域名是什么3个坑让实战项目部署翻车 域名是什么3个坑让实战项目部署翻车 刚接手一个 实战项目 部署,复制来的代码跑不通不知道怎么调。明明本地测试全绿,一上服务器就报 DNS 解析错误。别慌,这背后藏着 “ 域名是什么 ” 的核心考点。… · 2026/9/23 2:18:34
Calibre DRC/LVS物理验证实战:Runset编写与RVE排错指南 简介:这份Calibre DRC和LVS验证总结材料,是一份面向集成电路后端设计与验证工程师的中文入门与查漏补缺笔记。内容系统梳理了Mentor Calibre物理验证工具在DRC、LVS、ERC三个方面的核心应用,包括验证流程、规则文件结构、常用检查命令与简单规… · 2026/9/23 2:18:28
VLP16激光雷达实战配置指南:从物理连接到ROS2点云稳定输出 简介:本资源是Velodyne VLP-16激光雷达官方用户手册(DOCX格式),面向自动驾驶、机器人感知、三维建图等领域的工程师、高校研究人员及嵌入式开发者,解决设备安全操作、硬件连接、数据解析与故障排查等核心问题。手册涵盖… · 2026/9/23 2:18:28
万头攒动图解原理:3步解决代码卡顿,实测提速5倍 万头攒动图解原理:3步解决代码卡顿,实测提速5倍 复制来的代码跑不通,报错信息像天书,不知道从哪下手调?别慌,这行代码在 万头攒动 的并发场景下,就像早高峰的十字路口,谁先谁后全看运气,CPU 飙红只是表象。… · 2026/9/23 3:57:06
全栈AI修图Agent项目复盘:从Agent机制到多端架构实践 刚好上周把修图Agent的最后一个版本合到主干,前端、后端、AI编排、多端入口全部打通,这个全栈AI修图Agent项目算是真正完结了。趁热做个复盘,把整个项目的设计思路、技术选型、Agent机制拆解过程,以及实际推进中踩过的坑都整理出来… · 2026/9/23 3:56:47
3个坑讲透swort:版本升级API全变,面试必问 3个坑讲透swort:版本升级API全变,面试必问 刚把公司老项目从 swort v2.0 升到 v3.0,差点把发际线再削薄一厘米。 最崩溃的不是编译报错,而是发现文档里那套熟悉的 API 全变了。 以前靠 init() 和… · 2026/9/23 3:56:47
figures4papers:让AI Agent画出符合期刊规范的论文图表 1. 论文图表为什么一直是个"AI 翻车重灾区"我印象很深的一次:让 Codex 帮我画一张实验对比图,数据给得很完整,横纵坐标也交代清楚了,结果它交回来一张带着灰底色、积木式阴影、图例直接压在数据线上、字号小到要凑近屏幕… · 2026/9/23 3:56:41
DeepSeek API成本优化实战:混合路由与本地部署降本六成 先说个我自己的例子。之前有个自动化运营项目,每天要调用几千次 DeepSeek 模型做内容分类、结构化提取和工具调度,单个请求看着不贵,月底账单却让我差点从椅子上弹起来。后来我把整条调用链重新拆了一遍,做了一次"高成本替代… · 2026/9/23 3:56:41
3招搞定手机怎么下载微信面试难题实战项目解析 3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A… · 2026/9/23 0:00:03
你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 面试被问“高并发下如何保证消息不丢失”,你张口就是“用Redis”,结果面试官追问“如果Redis宕机了怎么办”,你瞬间卡壳。这种场景太常见了,很多新手在背八股文时,只记住了技术名词… · 2026/9/23 0:00:29