我要提问
ARTICLE DETAIL

资讯详情

前沿编程新知与开发实战干货的深度解读。

marimo 集成 Web 框架实战:用 FastAPI、Flask、FastHTML 托管与调用笔记本

marimo 集成 Web 框架实战:用 FastAPI、Flask、FastHTML 托管与调用笔记本 marimo 集成 Web 框架实战用 FastAPI、Flask、FastHTML 托管与调用笔记本【免费下载链接】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本篇基于仓库中 examples/frameworks/README.md 及其下六个可运行的完整示例展开讲解如何用marimo.create_asgi_app()把 marimo 笔记本挂载进 FastAPI、Flask、FastHTML 等 ASGI/WSGI 框架覆盖多笔记本目录批量服务、登录鉴权中间件含 WebSocket 场景的纯 ASGI 中间件写法、笔记本函数转为 API 端点等实战模式读者可以按文中步骤在本地复制并运行每一个示例。一、examples/frameworks 示例集概览examples/frameworks/README.md 说明了该目录的定位展示 marimo 与各类 Web/ASGI 框架FastAPI、Flask、FastHTML 等的集成方式并提示每个示例目录内都带有独立的README.md包含该示例的运行说明。目录下的实际示例包括示例目录演示能力examples/frameworks/fastapi/从目录批量创建多个 marimo 应用并挂载为单个 FastAPI 应用含登录鉴权、.env加载、日志examples/frameworks/fastapi-auth/推荐的鉴权模式纯 ASGI 中间件把用户信息注入scope[user]/scope[meta]笔记本内用mo.app_meta().request读取examples/frameworks/fastapi-endpoint/把笔记本中定义/计算逻辑转化为 FastAPI API 端点支持覆盖全局变量并取回 cell 输出examples/frameworks/fastapi-github/从一个 GitHub 仓库动态创建多个 marimo 应用并作为单个 FastAPI 应用服务examples/frameworks/flask/在 FlaskWSGI中批量服务 marimo 应用借助 Starlette 桥接examples/frameworks/fasthtml/用 FastHTML 从目录批量服务 marimo 应用所有示例都遵循同一运行方式文件顶部使用 PEP 723 内联脚本元数据声明依赖requires-python 3.12安装uv后在项目根执行uv run --no-project 目录/main.py即可自动解析依赖并启动例如# 在仓库根目录执行 uv run --no-project examples/frameworks/fastapi/main.py其中 FastAPI 版示例examples/frameworks/fastapi/main.py声明的依赖为fastapi、marimo、starlette、jinja2、itsdangerous、python-dotenv、python-multipart、passlib、pydantic、vega-datasets0.9.0Flask 版examples/frameworks/flask/main.py则是flask、marimo、asgiref、python-dotenv、flask-session、werkzeug、vega-datasets0.9.0。二、核心 APIcreate_asgi_app / with_app / build所有示例的骨架都是同一个三步调用链import marimo server marimo.create_asgi_app() # 1. 创建 ASGI 应用构建器 server server.with_app(path/app1, # 2. 逐个挂载笔记本 rootpath/to/nb.py) asgi_app server.build() # 3. 构建为可挂载的 ASGI 应用该 API 的源码位于 marimo/_server/asgi.py函数签名与文档字符串给出了全部可配置参数参数默认值作用quietFalse抑制标准输出include_codeFalse在页面中包含笔记本源码tokenNone应用鉴权 token不传则为空 tokenskew_protectionFalse启用版本偏斜保护中间件服务器更新后提示客户端重新加载session_ttl120会话存活时间秒asset_urlNone自定义静态资源加载地址支持{version}占位符如 CDN 地址redirect_console_to_browserFalse将 stdout/stderr 重定向到浏览器展示show_tracebacksFalse异常时弹出可查看完整 traceback 的提示框html_headNone注入每个笔记本页面head的自定义 HTMLexecute_opengraph_generatorsFalse执行 opengraph 生成器文档字符串还注明了一个适用前提该 ASGI 应用仅服务于处于 Run 模式app.run()的笔记本即应用模式而非编辑模式。从源码结构看ASGIAppBuilder内部会为每个挂载的笔记本维护一个应用缓存self._app_cache按缓存键分发http与websocket两类 scope并在某个挂载应用处理请求失败时回落到主应用marimo/_server/asgi.py这解释了为什么示例中可以先build()再整体mount到外层框架。三、FastAPI从目录批量挂载多个笔记本examples/frameworks/fastapi/README.md 说明该示例“从目录以编程方式创建多个 marimo 应用并作为单个 FastAPI 应用服务”包含登录鉴权、多应用目录服务、列出所有应用的首屏页、从.env加载环境变量、基础日志。核心逻辑见 examples/frameworks/fastapi/main.pyui_dir os.path.join(os.path.dirname(__file__), .., .., ui) # 即 examples/ui/ templates_dir os.path.join(os.path.dirname(__file__), templates) server marimo.create_asgi_app() app_names: list[str] [] for filename in sorted(os.listdir(ui_dir)): if filename.endswith(.py): app_name os.path.splitext(filename)[0] app_path os.path.join(ui_dir, filename) server server.with_app(pathf/{app_name}, rootapp_path) app_names.append(app_name)它遍历examples/ui/目录仓库中该目录下有slider.py、form.py、dataframe.py等 30 多个交互组件示例笔记本下每个.py文件以文件名为路由路径挂载。随后app FastAPI() templates Jinja2Templates(directorytemplates_dir) ... app.mount(/, server.build()) app.add_middleware( SessionMiddleware, secret_keyos.getenv(SECRET_KEY, your-secret-key) ) if __name__ __main__: import uvicorn uvicorn.run(app, hostlocalhost, port8000, log_levelinfo)示例同时实现了完整的登录流程/login提供表单页模板在 templates/login.htmlpost_login校验后写入request.session[username]auth_middleware拦截除/login外的所有请求未登录则 302 重定向到登录页首屏 templates/home.html 接收app_names渲染应用列表。模拟用户库users {admin: password123}在代码注释中明确标注“生产环境请替换为真实数据库”。四、推荐鉴权模式纯 ASGI 中间件 mo.app_meta().requestexamples/frameworks/fastapi-auth/README.md 给出的是“把用户信息传入 marimo 笔记本”的推荐模式并解释了关键设计决策marimo 使用 WebSocket 进行实时通信。Starlette 的BaseHTTPMiddleware只对 HTTP 请求生效在其中设置的scope[user]在 WebSocket 连接上不可见。纯 ASGI 中间件则两者都能处理。实现见 examples/frameworks/fastapi-auth/main.pyAuthMiddleware直接实现async def __call__(self, scope, receive, send)对http与websocket两类 scope 统一处理——已登录时在scope[user]写入{is_authenticated: True, username: ...}、scope[meta]写入{role: admin}未登录时对 WebSocket 直接close(code4003)对 HTTP 请求返回 302 跳/loginPUBLIC_PATHS {/login}中的路径放行。代码中还有一段关于中间件顺序的重要注释main.pyStarlette 中最后添加的中间件最外层、最先执行由于AuthMiddleware依赖SessionMiddleware先填充scope[session]所以要先add_middleware(AuthMiddleware)内层、后add_middleware(SessionMiddleware, secret_key...)外层。笔记本侧读取方式见 examples/frameworks/fastapi-auth/notebook.pyapp.cell def _(mo): req mo.app_meta().request user req.user if req else None meta req.meta if req else None mo.md(f ## User info from mo.app_meta().request - **user**: {user} - **username**: {user[username] if isinstance(user, dict) else N/A} - **meta**: {meta} )即通过mo.app_meta().request拿到外层中间件注入的user/meta无需修改笔记本本身。运行该示例后打开http://localhost:8000/用admin/password123登录cell 即显示注入的认证信息。五、把笔记本变成 API 端点函数即接口examples/frameworks/fastapi-endpoint/README.md 展示的是另一种用法——不渲染页面而是把 marimo 笔记本当作可导入的模块从中取函数与 cell 输出供任意 FastAPI 应用调用。两个能力点把 notebook 中定义的函数转为端点覆盖全局变量并取回 cell 输出。笔记本侧 examples/frameworks/fastapi-endpoint/notebook.py 用app.function装饰器声明纯函数add、greet、fibonacci、stats等并用app.cell组织了plot(plot_data)等依赖单元格文件尾部app.run()使其也能独立运行。服务侧 main.py 直接from notebook import add / greet / plotapp.get(/add/{a}/{b}) async def add_endpoint(request: Request, a: int, b: int) - int: from notebook import add return add(a, b) app.get(/plot) async def plot(request: Request): from notebook import plot data json.loads(request.query_params.get(data)) # 查询参数覆盖 output, _ plot.run(plot_datadata) # 覆盖变量并执行 cell buf io.BytesIO() output.save(buf, formatPNG) # 取回 matplotlib-PIL 输出 buf.seek(0) return StreamingResponse(contentbuf, media_typeimage/png)这里有两类调用方式值得注意直接调用app.function定义的普通函数add(1, 2)对含依赖关系的 cell 使用plot.run(plot_datadata)传入字典即可覆盖该 cell 的外部变量plot_data返回值是该 cell 的输出本例为Image从而把“查询参数 → 覆盖变量 → 执行 → 取输出 → 序列化为 PNG 流式响应”串成一条完整的 API 链路。按 README 的说明运行uv run --no-project examples/frameworks/fastapi-endpoint/main.py后执行curl http://localhost:8000/greet?namecoder即可验证首页/会返回一个 HTML 页面列出/add/1/2、/greet?nameWorld、/plot?data...三个可点击端点并显示当前 marimo 与 fastapi 版本。六、Flask 集成WSGI 与 ASGI 的桥接examples/frameworks/flask/README.md 的能力清单与 FastAPI 版一致登录、目录批量服务、首屏列表、.env、日志。由于 Flask 是 WSGI 框架而 marimo 的 ASGI 应用需要 ASGI 容器examples/frameworks/flask/main.py 的组装方式值得细看marimo_app marimo.create_asgi_app() for filename in sorted(os.listdir(ui_dir)): # 同样遍历 examples/ui/ if filename.endswith(.py): marimo_app marimo_app.with_app(pathf/{app_name}, rootapp_path) app_names.append(app_name) # 把 WSGI 的 Flask 包进 ASGI 容器 wsgi_app WSGIMiddleware(app) asgi_app Starlette(routes[ Route(/, endpointlambda request: RedirectResponse(url/flask/)), Mount(/flask, appwsgi_app), Mount(/, appmarimo_app.build()), ]) uvicorn.run(asgi_app, host0.0.0.0, port8000)要点Flask 应用经starlette.middleware.wsgi.WSGIMiddleware包装后与 marimo ASGI 应用一起挂进 Starlette 路由表最终由uvicorn以 ASGI 方式启动因此 README 特别注明“这会启动 Flask 开发服务器”底层其实是 uvicorn 承载。Flask 侧鉴权采用flask-sessionSESSION_TYPE filesystem与login_required装饰器密码用werkzeug.security.generate_password_hash/check_password_hash加盐哈希比 FastAPI 示例的明文比对更贴近生产习惯错误处理由app.errorhandler(401/404)渲染 templates/error.html。七、FastHTML 与从 GitHub 仓库服务笔记本examples/frameworks/fasthtml/README.md 说明该示例同样“从目录以编程方式创建多个 marimo 应用并作为单个 FastHTML 应用服务”结构与 FastAPI 版同构create_asgi_appwith_app循环 build挂载入口为 examples/frameworks/fasthtml/main.py。examples/frameworks/fastapi-github/ 则把笔记本来源从本地目录换成了远程README 描述其“从 GitHub 仓库以编程方式创建多个 marimo 应用并作为单个 FastAPI 应用服务”同样带有应用列表首屏与基础日志main.py 拉取仓库中的.py文件后再逐一走with_app挂载适合“笔记本即内容”、随仓库更新即随站点更新的发布场景页面模板位于 templates/home.html。八、模式小结与复用建议综合六个示例marimo 与 Web 框架的集成可以归纳为三种递进模式整站托管Run 模式应用create_asgi_app()→ 循环with_app(path, root)→build()→mount到外层框架任意位置。FastAPI/Flask/FastHTML/GitHub 四个示例都是这一模式差别只在外层框架与笔记本来源本地目录 vs 远程仓库。鉴权增强在 ASGI 层用纯中间件写scope[user]/scope[meta]笔记本内通过mo.app_meta().request消费注意中间件必须同时覆盖http与websocket两类 scope且注意 Starlette 中间件的添加顺序与执行顺序相反。函数级复用不启动页面直接导入笔记本模块调用app.function定义的普通函数或用cell.run(变量值)覆盖外部变量执行 cell 并取回输出如图片、数据再序列化为任意 API 响应。所有示例均可用uv run --no-project main.py直接运行验证若需要向社区贡献新的框架示例参考 examples/frameworks/README.md 的建议为示例目录补上README.md运行说明并提交即可。【免费下载链接】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),仅供参考
返回列表