以编程方式运行 marimo 后端:基于 ASGI 与 FastAPI 的应用集成部署指南
以编程方式运行 marimo 后端基于 ASGI 与 FastAPI 的应用集成部署指南【免费下载链接】marimoA reactive notebook for Python — run reproducible experiments, query with SQL, execute as a script, deploy as an app, and version with git. Stored as pure Python. All in a modern, AI-native editor.项目地址: https://gitcode.com/GitHub_Trending/ma/marimo本文面向需要把 marimo 响应式笔记本嵌入到自有 Python Web 服务的开发者通过marimo.create_asgi_app()这一公开 API可以在一套 ASGI/FastAPI 应用中挂载一个或多个 marimo 应用并自由叠加认证、路由、错误处理等自定义中间件。读完本文你将掌握静态挂载with_app、动态目录with_dynamic_directory、在笔记本内访问请求数据mo.app_meta().request、查询参数校验以及底层内核模型与横向扩展约束能够独立搭建登录保护 多 notebook 仪表盘一体的生产级部署。为什么需要以编程方式运行 marimo 后端日常开发中我们通常用marimo edit/marimo run命令启动编辑器或应用。但当 marimo 只是更大应用的一部分时——例如需要与已有 FastAPI 服务共享端口、需要自定义认证逻辑、需要把十几个 notebook 聚合到一个域名下、需要为不同路由挂不同中间件——命令行启动方式就不够用了。marimo 为此提供了模块级编程接口核心入口是定义在 marimo/_server/asgi.py 中的create_asgi_app()。它返回一个ASGIAppBuilder构建器通过链式调用声明挂载点最终build()出一个标准 ASGI 应用ASGIApp可以被任何 ASGI 服务器uvicorn 等直接运行也可以被 FastAPI/Starlette 通过app.mount(/, ...)挂载为子应用。从源码看create_asgi_app()内部完成了几件关键工作marimo/_server/asgi.py使用get_default_config_manager()读取默认配置创建基于 Starlette 的base_app若未显式传入token默认使用空令牌AuthToken()——也就是说默认不做鉴权作者需要自己提供 AuthN/AuthZ强制校验pyzmq依赖已安装DependencyManager.zmq.require(...)因为每个 notebook 的运行时内核依赖它每个挂载的 notebook 都会创建独立的SessionManagerSessionMode.RUN即仅运行模式不启动 LSP 服务并复用同一份create_asgi_app级配置。create_asgi_app 参数详解create_asgi_app()的完整签名与参数语义可直接在源码 docstring 中确认marimo/_server/asgi.py参数类型默认值作用quietboolFalse是否抑制标准输出include_codeboolFalse是否把 notebook 代码包含进应用前端可查看代码tokenstr | NoneNone应用鉴权令牌不传则使用空令牌即关闭内置鉴权交由上层中间件处理skew_protectionboolFalse启用版本偏差保护中间件服务器更新后提示客户端刷新避免前后端版本不一致session_ttlint120会话存活时间秒默认 120 秒2 分钟asset_urlstr | NoneNone自定义静态资源 URL支持{version}占位符例如 CDN 地址redirect_console_to_browserboolFalse是否把 stdout/stderr 重定向到浏览器控制台显示show_tracebacksboolFalse出错时是否以模态框展示完整 traceback源码中会通过配置覆盖注入到每个 app见 marimo/_server/asgi.pyhtml_headstr | NoneNone注入每个 notebook 页面head的自定义 HTML用于全局分析脚本、自定义样式、meta 标签notebook 自带html_head_file配置时全局内容先注入、notebook 内容随后注入execute_opengraph_generatorsboolFalse解析元数据时是否执行 notebook 内定义的 OpenGraph 生成器仅对可信目录的 notebook 开启FastAPI 集成示例把 marimo 应用嵌入 FastAPI 的最小完整示例与官方文档一致可在 examples/frameworks/fastapi/main.py 看到同款生产级实现from typing import Annotated, Callable, Coroutine from fastapi.responses import HTMLResponse, RedirectResponse import marimo from fastapi import FastAPI, Form, Request, Response # 创建 marimo asgi 应用 server ( marimo.create_asgi_app() .with_app(path, root./pages/index.py) .with_app(path/dashboard, root./pages/dashboard.py) .with_app(path/sales, root./pages/sales.py) ) # 创建 FastAPI 应用 app FastAPI() app.add_middleware(auth_middleware) app.add_route(/login, my_login_route, methods[POST]) app.mount(/, server.build()) # 运行服务器 if __name__ __main__: import uvicorn uvicorn.run(app, hostlocalhost, port8000)几个关键点with_app(path, ...)挂载在根路径作为默认/首页应用build()内部会对挂载列表按路径长度降序排序确保根路径应用最后挂载见 marimo/_server/asgi.py对非空路径如/dashboard构建器会自动注册一条301重定向路由把/dashboard重定向到/dashboard/避免尾斜杠缺失导致 404见 marimo/_server/asgi.pyFastAPI 自有路由如/login与 marimo 挂载在同一应用上二者互不冲突。静态资源与认证豁免注意在这种模式下marimo 会把静态资源挂载在notebook 名称之下例如上例中就是http://hostname/dashboard|sales/assets/assetname.css|js|...。如果你使用了自定义授权中间件务必对这些静态资源路径跳过认证检查——它们的数量非常多如果每个资源都触发一次鉴权往返页面加载会被严重拖慢。可以在中间件里通过request.url.path判断前缀/assets/后直接放行仓库的冒烟测试 marimo/_smoke_tests/custom_server/my_server.py 中即是先放行/login、再校验 cookie 令牌的模式。完整示例的进一步参考仓库中的 examples/frameworks/fastapi/main.py 是一个更完整的参考实现它演示了遍历目录批量把每个.pynotebook 挂载成独立路由for filename in sorted(os.listdir(ui_dir))基于 Session 的登录/登出流程SessionMiddlewareJinja2Templates首页列出所有已挂载应用并支持跳转.env环境变量加载与日志配置。对应 READMEexamples/frameworks/fastapi/README.md说明其运行方式为uv run --no-project main.py。静态目录遍历批量挂载如果目录中的 notebook 基本不变用with_app加循环遍历是更推荐的方式——每个 notebook 在启动时就静态注册路由固定、行为可预期from pathlib import Path server marimo.create_asgi_app() app_names: list[str] [] notebooks_dir Path(__file__).parent / notebooks for filename in sorted(notebooks_dir.iterdir()): if filename.suffix .py: app_name filename.stem server server.with_app(pathf/{app_name}, rootfilename) app_names.append(app_name)with_app的签名源码 marimo/_server/asgi.py为with_app(*, path: str, root: str, middleware: list[MiddlewareFactory] | None None)其中path应用挂载的 URL 路径rootnotebook 文件路径middleware可选仅应用于该子应用的中间件工厂列表。注意构建器会为每个唯一root缓存并复用已创建的 ASGI 子应用self._app_cache相同文件不会重复创建会话见 marimo/_server/asgi.py。动态目录with_dynamic_directory当目录内容频繁变化例如仪表盘 notebook 会新增、删除且你不想为每次变更重启服务器时使用with_dynamic_directoryserver ( marimo.create_asgi_app() .with_dynamic_directory(path/dashboard, directory./notebooks) )其完整签名marimo/_server/asgi.py为with_dynamic_directory( *, path: str, directory: str, validate_callback: ValidateCallback | None None, middleware: list[MiddlewareFactory] | None None, ) - ASGIAppBuilder其中validate_callback的类型别名是Callable[[str, Scope], Awaitable[bool] | bool]marimo/_server/asgi.py它接收应用路径与请求 scope返回布尔值表示该应用是否允许访问非常适合插入认证/授权逻辑回调中也可以主动抛出带status_code与headers的异常来返回自定义错误信息。从DynamicDirectoryMiddleware的实现marimo/_server/asgi.py可以梳理出该模式的底层行为路由解析请求路径去掉base_path前缀后先按相对路径.py直接匹配再按前缀逐级尝试嵌套匹配_find_matching_filemarimo/_server/asgi.py支持多级子目录结构安全防护显式拒绝..路径穿越段包括把\归一化为/后检查防止 Windows 风格分隔符绕过并用path.resolve().relative_to(directory.resolve())实时校验目标文件确实位于目录内marimo/_server/asgi.py应用缓存与惰性加载每个匹配到的 notebook 首次请求时才创建对应 ASGI 子应用并缓存在_app_cache目录内容变化无需重启这也是动态的来源marimo/_server/asgi.py尾斜杠重定向HTTP 请求若缺少尾斜杠且无剩余路径会返回307重定向补齐/marimo/_server/asgi.py子路径挂载兼容当该 ASGI 应用被父框架挂载到子路径如app.mount(/server2, ...)时会正确处理root_path与路径前缀的剥离逻辑marimo/_server/asgi.py。仓库冒烟测试 marimo/_smoke_tests/custom_server/my_server.py 同时验证了根挂载与/server2子路径挂载两种场景并注明是对某个 GitHub issue 的回归测试。一个可供参考的冒烟测试组合展示了with_appwith_dynamic_directory 根应用混用的完整形态marimo/_smoke_tests/custom_server/my_server.pyserver1 ( marimo.create_asgi_app() .with_app(path/dataframes, rootstr(dirname / dataframe.py)) .with_dynamic_directory(path/charts, directorystr(dirname / altair_examples)) .with_dynamic_directory(path/smoke_tests, directorystr(dirname)) .with_app(path, rootstr(dirname / buttons.py)) )在笔记本内访问请求数据mo.app_meta().request以编程方式挂载的 notebook 中可以通过mo.app_meta().request拿到当前 HTTP 请求数据这对实现认证、展示用户信息非常有用import marimo as mo # 在 notebook 中访问请求数据 request mo.app_meta().request if request and request.user and request.user[is_authenticated]: content fWelcome {request.user[username]}! else: content Please log in mo.md(content)AppMeta.request属性定义在 marimo/_runtime/app_meta.py它从运行时上下文中读取请求未初始化时返回None。其返回类型是HTTPRequest定义于 marimo/_runtime/commands.py这是一个可 pickle 的 dataclass只包含安全的请求子集具体字段字段含义request.headers请求头已剔除marimo/x-marimo前缀的内部头request.cookies请求 Cookierequest.query_params查询参数映射为dict[str, list[str]]request.path_params路由路径参数request.user由认证中间件写入的用户数据request.urlURL 信息含path、port、scheme、netloc、query、hostnamerequest.base_url序列化的基础 URLrequest.meta自定义中间件写入的元数据特别值得注意的设计HTTPRequest刻意不包含 session 与 auth 字段源码注释明确说明they may contain information that the app author does not want to expose避免应用作者无意间暴露敏感数据。认证中间件实现要让request.user有值需要实现一个纯 ASGI 中间件重要警告请使用纯 ASGI 中间件而不是 Starlette 的BaseHTTPMiddleware这样才能保证scope[user]和scope[meta]对HTTP 和 WebSocket连接都生效。marimo 使用 WebSocket 做实时通信而BaseHTTPMiddleware只处理 HTTP 请求。class AuthMiddleware: def __init__(self, app): self.app app async def __call__(self, scope, receive, send): if scope[type] in (http, websocket): # 向请求 scope 中写入用户数据 # 该数据可通过 mo.app_meta().request.user 访问 scope[user] { is_authenticated: True, username: example_user, # 可添加任意其他用户数据 } # 可选向请求添加元数据 scope[meta] { some_key: some_value, } await self.app(scope, receive, send) # 将中间件添加到 FastAPI 应用 app.add_middleware(AuthMiddleware)其数据链路在源码中清晰可循中间件向 ASGIscope写入user/meta后HTTPRequest.from_request通过_user_to_dict(request.get(user))与_meta_to_dict(request.get(meta))将其序列化进HTTPRequestmarimo/_runtime/commands.pynotebook 侧再经mo.app_meta().request读取marimo/_runtime/app_meta.py。仓库的 FastAPI 示例 examples/frameworks/fastapi/main.py 展示了更贴近生产的会话式认证登录后把用户名写入 session中间件对所有非/login请求校验 session未登录则302重定向到登录页。文档化并校验查询参数挂载的应用接收查询参数时可以借助 Pydantic 模型声明、校验并文档化这些参数。假设 marimo 应用notebooks/items.py被挂载到/items那么可以在 FastAPI 中声明同路由的端点查询参数先经过 Pydantic 模型校验再重定向到 marimo 端点校验失败时 FastAPI 会自动返回 422 及清晰错误信息从而起到文档化 校验的双重作用# src/main.py from fastapi import FastAPI, Request, Query from fastapi.responses import RedirectResponse from marimo import create_asgi_app from pathlib import Path from pydantic import BaseModel, Field from typing import Annotated, Literal from urllib.parse import urlencode app FastAPI() class FilterParams(BaseModel): limit: int Field(100, gt0, le100) offset: int Field(0, ge0) order_by: Literal[created_at, updated_at] created_at tags: list[str] [] app.get(/items) async def marimo_items( request: Request, filter_query: Annotated[FilterParams, Query()] ): query_params urlencode(filter_query.model_dump(), doseqTrue) return RedirectResponse(urlf/items/?{query_params}) server create_asgi_app(include_codeTrue, quietFalse) notebooks_dir Path(__file__).parent.parent / notebooks for filename in notebooks_dir.iterdir(): if filename.suffix .py: app_name filename.stem server server.with_app(pathf/{app_name}, rootfilename) app.mount(/, server.build())要点说明FilterParams对每个字段声明了默认值与约束limit在 1100、offset非负、order_by限定枚举、tags支持列表Pydantic 校验不通过时 FastAPI 会直接返回 422校验通过后使用urlencode(..., doseqTrue)把model_dump()的结果重新编码为查询串doseqTrue保证tags这类列表参数正确展开然后RedirectResponse指向 marimo 端点/items/该模式在文档 docs/api/query_params.md 中亦有呼应notebook 内部可用mo.query_params读取这些参数并用 Pydantic 模型如 RGB 通道字段设置 UI 初始状态。底层机制与横向扩展约束Under the Hood在这种模式下marimo 会为每个新会话/每个挂载应用在独立子线程中同一进程内启动一个新的计算内核。由此带来性能和可靠性方面的影响必须启用粘性会话sticky sessions如果运行多个相同服务器实例做负载均衡负载均衡器必须确保同一客户端每次请求都命中同一实例——因为用户的内核只存在于其首次连接的那台服务器上同一节点上多进程不可靠在同一节点运行同一 FastAPI 进程的多个实例Python Web 服务的常见做法无法可靠工作因为实际运行内核的只会是其中一个实例扩展建议上述方案的横向扩展存在天然上限官方建议优先纵向扩展——先提升容器 CPU/内存规格再考虑增加容器实例数。补充一个源码层面的背景create_asgi_app()创建每个子应用时读取实验性配置experimental.isolate_apps默认False见 marimo/_server/asgi.py用于控制是否对应用做进程级隔离。仓库中的进程隔离冒烟测试 marimo/_smoke_tests/process_isolation/serve.py 说明了这一特性解决的问题当两个 notebook 各自 import 同名但内容不同的模块时进程隔离能避免sys.modules相互污染该脚本用create_asgi_app()挂载两个应用并验证各自输出 PASS/FAIL。这也意味着在评估每个应用一个内核的部署成本时需要考虑内核/进程数量随 notebook 数量线性增长。小结marimo.create_asgi_app()提供了一条干净的编程式嵌入路径with_app适合静态路由、with_dynamic_directory适合频繁变动的目录、mo.app_meta().request打通了 notebook 与 Web 请求之间的数据通道而纯 ASGI 中间件 Pydantic 查询参数校验则让认证与参数治理完全可控。部署时只需记住两条铁律静态资源路径要在鉴权中间件中豁免多实例部署必须开启粘性会话并优先纵向扩容。完整的可运行参考与冒烟测试分别位于 examples/frameworks/fastapi/main.py 与 marimo/_smoke_tests/custom_server/my_server.py。【免费下载链接】marimoA reactive notebook for Python — run reproducible experiments, query with SQL, execute as a script, deploy as an app, and version with git. Stored as pure Python. All in a modern, AI-native editor.项目地址: https://gitcode.com/GitHub_Trending/ma/marimo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

客服自动化实战:用Dify与浏览器自动化优化流程

客服自动化实战:用Dify与浏览器自动化优化流程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/13 21:44:16 阅读更多 →
This is a test repo.

This is a test repo.

This is a test repo. 【免费下载链接】OI-wiki :star2: Wiki of OI / ICPC for everyone. (某大型游戏线上攻略,内含炫酷算术魔法) 项目地址: https://gitcode.com/GitHub_Trending/oi/OI-wiki This repo includes some c codes. rea…

2026/9/13 21:43:16 阅读更多 →
Web安全入门与实战:从漏洞原理到服务器加固

Web安全入门与实战:从漏洞原理到服务器加固

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/13 21:43:16 阅读更多 →

最新新闻

AI Agent浏览器交互实战:从CDP到MCP的选型与实现

AI Agent浏览器交互实战:从CDP到MCP的选型与实现

如果你正在做 AI Agent,不管你是用 LangGraph 自己搭、在 n8n 里拖流程,还是拿现成框架做二次开发,大概率会在某个环节撞上同一个问题:浏览器交互能力。比如你让 Agent 去查资料,它可以很快生成一堆检索词,…

2026/9/15 0:06:24 阅读更多 →
MBOT:轻量级Python多智能体协作仿真范式

MBOT:轻量级Python多智能体协作仿真范式

简介:本资源是一套面向计算机及相关专业本科生的多智能体协作仿真教学实践项目,适用于毕业设计、课程大作业及AI方向自主学习者,聚焦Python实现的MBOT多智能体协同建模与仿真实战。压缩包共33个文件(805KB)&#xff0c…

2026/9/15 0:06:24 阅读更多 →
芯片CAD图纸转SVG矢量方案与TinyMCE集成

芯片CAD图纸转SVG矢量方案与TinyMCE集成

1. 芯片制造企业CAD图纸处理的核心挑战在芯片设计制造领域,CAD图纸是工程师的"设计语言"。这些图纸通常包含复杂的电路布局、器件结构和工艺参数,需要精确到微米级别的细节呈现。当这些专业图纸需要嵌入到网页编辑器(如TinyMCE&…

2026/9/15 0:06:24 阅读更多 →
OpenSpec与智能体技术在后端工程中的实践应用

OpenSpec与智能体技术在后端工程中的实践应用

1. 项目概述:OpenSpec与智能体在后端工程中的融合实践在后端开发领域,工程化实践一直是提升交付质量与效率的关键。最近三个月,我主导了一个结合OpenSpec规范与智能体技术的企业级后端项目,期间经历了从工具选型到落地实施的全过程…

2026/9/15 0:06:24 阅读更多 →
激光三维扫描技术在骨骼测量中的应用与优化

激光三维扫描技术在骨骼测量中的应用与优化

1. 人体遗骸三维扫描的技术背景与挑战在法医人类学、考古研究和医学教育领域,对人体骨骼遗骸进行精确三维数字化记录的需求日益增长。传统测量方法依赖卡尺、角度仪等接触式工具,不仅效率低下,而且难以记录复杂曲面特征。光学三维扫描技术的出…

2026/9/15 0:06:24 阅读更多 →
Spring Boot性能优化实战:从原理到应用

Spring Boot性能优化实战:从原理到应用

1. Spring Boot性能优化的核心价值在当今快节奏的互联网时代,应用性能直接影响用户体验和业务转化率。Spring Boot作为Java生态中最流行的应用框架,其性能表现关乎千万级应用的运行效率。根据实际压力测试数据,经过系统优化的Spring Boot应用…

2026/9/15 0:05:24 阅读更多 →

日新闻

Java高级技术:从语言特性到性能优化全解析

Java高级技术:从语言特性到性能优化全解析

1. Java高级技术概述Java作为一门成熟的编程语言,经过二十多年的发展已经形成了完整的生态系统。在企业级应用开发、大数据处理、移动开发等领域,Java都占据着重要地位。掌握Java高级技术不仅意味着能够编写更高效的代码,更代表着开发者能够解…

2026/9/15 0:00:23 阅读更多 →
C#与Halcon结合的工业视觉处理实战指南

C#与Halcon结合的工业视觉处理实战指南

1. 项目概述:C#与Halcon强强联合的视觉处理利器这个基于C#和Halcon的视觉处理Demo项目,是我在工业质检领域摸爬滚打多年后提炼出的实战精华。它完美融合了C#的界面开发优势与Halcon强大的图像处理能力,就像给视觉工程师配上了一把瑞士军刀。项…

2026/9/15 0:00:23 阅读更多 →
32路工业串口服务器的硬核选型指南:确定性、鲁棒性与协议下沉

32路工业串口服务器的硬核选型指南:确定性、鲁棒性与协议下沉

1. 为什么“32路复合型”不是营销话术,而是工业现场真实痛点的硬解你有没有遇到过这样的场景:在某大型能源站的PLC机柜里,十几台不同年代、不同品牌的温控仪、电表、气体分析仪、阀门控制器,全靠RS-485总线挂在一根线上&#xff0…

2026/9/15 0:00:23 阅读更多 →

周新闻

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验 【免费下载链接】ai The AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and ag…

2026/9/14 5:45:49 阅读更多 →
Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化 【免费下载链接】refine A React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility. 项目地址: https://gitcode.com/GitH…

2026/9/14 0:52:26 阅读更多 →
Flutter应用改名全指南:从Android到iOS的配置与工具实践

Flutter应用改名全指南:从Android到iOS的配置与工具实践

刚接一个外包项目时,甲方要求把工程里临时用的应用名改成正式产品名。我本来觉得“改名”这种小事,打开配置文件改一行不就完了?结果真动手才发现,Flutter项目里“应用名称”根本不是一处配置,而是一整套散落在 Androi…

2026/9/14 0:06:41 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/14 17:35:10 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/14 16:59:29 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/14 5:45:14 阅读更多 →