marimo 单元格输出机制全解析:从最后表达式到 mo.output 命令式输出
marimo 单元格输出机制全解析从最后表达式到 mo.output 命令式输出【免费下载链接】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 响应式笔记本中每个单元格cell都可以拥有一个可视化的输出output编辑模式下它显示在单元格上方代码则像图注一样衬在下文把笔记本作为应用运行时界面上展示的正是各个单元格输出的集合。本文围绕docs/examples/outputs/basic_output.md对应的示例 cell_output.py结合marimo/_runtime/output/_output.py、marimo/_output/formatting.py、marimo/_output/show_code.py等源码系统讲解单元格输出的默认规则、命令式输出 API、控制台输出分流以及与应用视图的关系帮助你掌握在 marimo 中掌控输出的完整能力。一、示例文档与示例代码cell_output 的基本语义关联文档 basic_output.md 是一个 marimo 嵌入式示例页面通过marimo-embed-file指令直接嵌入 cell_output.py/// marimo-embed-file size: xxlarge mode: edit filepath: examples/outputs/cell_output.py ///size: xxlarge指定嵌入区域为超大尺寸mode: edit表示以编辑模式呈现读者可以看到代码与输出并列filepath指向仓库中真实的示例文件。也就是说这个文档的正文本身就是一段可运行的 marimo 笔记本代码其核心内容全部体现在示例文件中这也是理解 marimo 输出语义最直接的入口。示例代码 cell_output.py 由三个单元格构成__generated_with 0.19.7标明生成版本app marimo.App()创建应用对象import marimo __generated_with 0.19.7 app marimo.App() app.cell def _(mo): mo.md( The last expression of a cell is its visual output. This output appears above the cell when editing a notebook, with notebook code serving as a caption for the output. Outputs can be configured to appear below cells in the user settings. If running a notebook as an app, the output is the visual representation of the cell (code is hidden by default). ) return app.cell def _(): Hello, world! return app.cell def _(): import marimo as mo return (mo,) if __name__ __main__: app.run()三个单元格分别演示了三层含义用mo.md生成富文本输出第一个单元格的输出是一段 Markdown它同时承担了文档说明的职责展示了代码即文档、文档即输出的 marimo 风格字符串字面量即输出第二个单元格只有一行Hello, world!没有任何print——在 marimo 中单元格的最后一个表达式就是它的可视输出因此字符串会被直接渲染出来模块导入与依赖第三个单元格通过return (mo,)把marimo模块暴露给其他单元格使用这体现了 marimo 的依赖图机制——单元格之间通过显式的返回变量建立数据流。二、核心规则单元格的最后一个表达式就是它的输出从源码角度印证最后表达式即输出这一规则。在运行时层面marimo 的单元格执行器会捕获单元格体执行完毕后的最终值作为RunResult的output字段传递给后续的渲染流程见 evaluator.py 中execute_cell_async的调用与RunResult(outputvalue, exceptionNone)的构造。这条规则带来的关键行为是无print也能显示Hello, world!作为表达式求值后被渲染到输出区这与 Jupyter 中仅最后一个表达式自动显示的语义一致输出是替换而非累积单元格每次执行输出区都会被最后一次执行的结果整体替换返回None则不产生输出例如示例中导入单元格返回的是(mo,)元组而非None才会在界面中展示marimo模块的渲染结果。如果单元格最终表达式求值为None输出区为空。在编辑界面中输出默认出现在单元格上方代码作为输出的说明文字排布其下用户也可以在设置中把输出改为显示在单元格下方。而当我们用marimo run把笔记本作为应用运行时输出就是该单元格的可视化呈现——代码默认被隐藏。三、用mo.md构建富文本输出单元格输出最常见的载体是mo.md()。它接受一个 Markdown 字符串并返回一个Html对象该对象作为单元格的最后表达式时会被渲染成富文本。marimo 对 Markdown 做了扩展详见 docs/guides/outputs.md 与marimo/_output/md.py插值 Python 值使用 f-string 可以把 Python 变量嵌入 Markdown甚至直接嵌入 marimo 的 UI 元素marimo 会自动识别并渲染它们LaTeX 支持在 Markdown 编辑器中可启用r原始字符串模式书写 LaTeX 公式扩展语法支持/// details | 标题折叠块、/// attention | 标题等 admonition 提示框、:emoji:表情语法。例如import marimo as mo name mo.ui.text(placeholderYour name here) mo.md( f Hi! Whats your name? {name} )mo.md(fHello, {name.value}!)对于 matplotlib 等第三方绘图对象可以直接用mo.as_html(figure)包装后嵌入 Markdown从而接入 marimo 的媒体查看器mo.md( f Heres a plot! {mo.as_html(figure)} )值得注意的细节示例 cell_output.py 中mo.md(...)是单元格的最后一个表达式因此它的渲染结果直接成为输出——这正是Markdown 即输出的典型用法。四、命令式输出mo.output.replace/append/clear/replace_at_index虽然最后表达式即输出已能满足多数场景但有时需要在单元格运行过程中增量构建输出。marimo 为此提供了命令式输出 API实现在 marimo/_runtime/output/_output.py 中。4.1mo.output.replace(value)把单元格的整个输出区替换为value。源码逻辑是获取当前执行上下文后先output.clear()再对value调用formatting.as_html(value)统一转成 HTML随后output.append(html)并通过write_internal广播给前端。也就是说replace之后单元格输出区只有这一个对象。4.2mo.output.append(value)把value追加到输出区末尾多个追加对象在界面上纵向堆叠。源码中每次append后都会把整个output.stack()重新广播到前端保证界面与内存中的输出栈一致。4.3mo.output.replace_at_index(value, idx)按索引替换输出栈中的某个对象当idx等于当前输出长度时等价于一次append。这在需要更新输出列表中特定位置例如更新图表、只刷新某一节文本时非常有用。4.4mo.output.clear()清空单元格输出区。源码中它实际上是replace(None)的别名即清空后不写入任何对象。4.5 重要警告最后一个表达式会替换已有输出在 docs/api/outputs.md 中有一条醒目的警告以非None表达式结尾的单元格等价于在该表达式上调用mo.output.replace()——它会替换你之前用命令式 API 写入的所有输出。如果希望保留已有输出并追加新内容请用mo.output.append包裹最后一个表达式。mo.output.append(first) mo.output.append(second) # 若这里直接写 third前面的 first/second 会被整体替换掉 # 正确做法 mo.output.append(third)底层容器是marimo/_runtime/cell_output_list.py中的CellOutputList——一个线程安全的输出栈内部持有RLock锁append、clear、replace_at_index等操作都在锁保护下进行因此跨线程增量更新输出也是安全的。五、输出如何被渲染格式化协议与媒体查看器命令式 API 内部统一调用formatting.as_html(value)其核心是 marimo 的格式化协议定义于 marimo/_output/formatting.py每个格式化器是一个Callable[[T], tuple[KnownMimeType, str]]输入对象、输出(MIME 类型, 数据)二元组注册优先级先查顶层类型的注册格式化器再沿类型的 MRO 继承链向上查找找不到才退回到通用表示用户自定义对象有两条接入路径在类上实现_mime_方法返回(mime, data)或通过FormatterRegistry.add_formatter(type, func)注册一个格式化函数对文本、JSON、DataFrame、matplotlib 图、音频、视频等常见类型marimo 内置了丰富的格式化器见marimo/_output/formatters/目录输出时统一按 MIME 类型交给前端的媒体查看器渲染。这意味着任何 Python 对象只要满足格式化协议就能作为单元格输出被优雅地展示——不必是字符串或 HTML。六、控制台输出 vs 单元格输出print、日志等写入stdout/stderr的内容属于控制台输出默认显示在单元格下方的控制台区域不会进入输出区也不会出现在应用视图中。这一区分在 docs/api/outputs.md 的 Console outputs 一节中有明确说明。若希望控制台输出并入输出区从而在应用中可见marimo 提供详见 marimo/_runtime/output/_output.py 与marimo/_runtime/redirect_streams.pymo.redirect_stdout()/mo.redirect_stderr()上下文管理器把print输出重定向到单元格输出区with mo.redirect_stdout(): print(Hello, world!)mo.capture_stdout()/mo.capture_stderr()捕获但不重定向适合把输出转成字符串再自行处理mo.output.clear_console()清空当前单元格的控制台输出区包括本次运行中已写入的print/日志。此外配置项中的std_stream_max_bytes会限制控制台输出的最大字节数参见 config.py 中相关文档字符串output_max_bytes则限制单元格输出的最大字节数——两者都关系到前端性能超过限制的输出会被截断。七、在应用视图中展示代码mo.show_code应用模式下代码默认隐藏。如果希望某个单元格的代码连同输出一起展示在应用视图中可以使用mo.show_code()实现在 marimo/_output/show_code.pydef factorial(n: int) - int: if n 0: return 1 return n * factorial(n - 1) mo.show_code(factorial(5))# 只展示代码不展示输出 mo.show_code()关键行为源码可验证参数position控制代码相对输出的位置above代码在上或below默认代码在下内部用vstack把只读code_editor与输出纵向堆叠显示出的代码会通过substitute_show_code_with_arg把代码中所有mo.show_code(...)递归替换为...避免死循环展示show_code()不带参数时只渲染一个只读代码编辑器用于代码即输出的展示场景在ContextNotInitializedError非笔记本运行环境下退化为直接返回as_html(output)保证脚本环境不报错。八、小结marimo 输出体系一览能力API / 规则源码位置默认输出单元格最后一个表达式executor/evaluator.py富文本输出mo.md() Markdown 扩展marimo/_output/md.py替换输出mo.output.replace(value)marimo/_runtime/output/_output.py追加输出mo.output.append(value)同上按索引替换mo.output.replace_at_index(value, idx)同上清空输出mo.output.clear()即replace(None)同上线程安全输出栈CellOutputListmarimo/_runtime/cell_output_list.py格式化协议_mime_方法 / 注册 formattermarimo/_output/formatting.py控制台输出print→ 单元格下方控制台区marimo/_runtime/redirect_streams.py输出代码同显mo.show_code(output, position...)marimo/_output/show_code.py实践建议默认场景下让单元格的最后一个表达式成为输出即可需要边运行边累积时使用mo.output.append需要整体替换时用mo.output.replace但务必记得最后一个非None表达式会替换已有输出这一陷阱。理解输出与代码、控制台、应用视图三层关系是写出界面友好、可复用、可直接发布为应用的 marimo 笔记本的基础。更多输出类型DataFrame、图表、进度条、媒体等可进一步阅读 guides/outputs.md 与 api/outputs.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),仅供参考

相关新闻

Bun 运行时深度解析:架构差异、性能优势与工程落地指南

Bun 运行时深度解析:架构差异、性能优势与工程落地指南

/* 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 22:14:41 阅读更多 →
lo 库 it.FilterMapToSeq 实战指南:把 map 惰性转换为过滤后的 iter.Seq 序列

lo 库 it.FilterMapToSeq 实战指南:把 map 惰性转换为过滤后的 iter.Seq 序列

lo 库 it.FilterMapToSeq 实战指南:把 map 惰性转换为过滤后的 iter.Seq 序列 【免费下载链接】lo 💥 A Lodash-style Go library based on Go 1.18 Generics (map, filter, contains, find...) 项目地址: https://gitcode.com/GitHub_Trending/lo/lo …

2026/9/13 22:14:41 阅读更多 →
双层规划与雨流计数法在电力系统优化中的应用

双层规划与雨流计数法在电力系统优化中的应用

/* 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 22:13:41 阅读更多 →

最新新闻

如何用 enterprise-search 插件的 /digest 生成每日或每周活动摘要来快速补进度

如何用 enterprise-search 插件的 /digest 生成每日或每周活动摘要来快速补进度

如何用 enterprise-search 插件的 /digest 生成每日或每周活动摘要来快速补进度 【免费下载链接】knowledge-work-plugins Open source repository of plugins primarily intended for knowledge workers to use in Claude Cowork 项目地址: https://gitcode.com/GitHub_Tren…

2026/9/13 23:08:05 阅读更多 →
车载工控系统量产落地:从控制核心到三防移动端的全链路实践

车载工控系统量产落地:从控制核心到三防移动端的全链路实践

1. 项目概述:这不是一次简单的硬件选型,而是一场面向量产的系统性工程攻坚“2026车载工控深潜”这个标题里,“2026”不是随便写的年份——它代表的是当前整车厂(OEM)和一级供应商(Tier 1)正在密…

2026/9/13 23:08:05 阅读更多 →
基于 SuperMap iClient for Leaflet 实现鼠标悬停路由实时获取里程值

基于 SuperMap iClient for Leaflet 实现鼠标悬停路由实时获取里程值

一、引言:从“静态查询”到“动态交互” 在实际 GIS 应用中,有时需要查询道路上任意位置的里程值(例如公路桩号里程、管道长度等)。最近在对接项目时,就遇到这样一个需求:用户希望在路线图上通过鼠标悬停来…

2026/9/13 23:08:05 阅读更多 →
Java后端必懂的网络基础:分层、TCP/IP、HTTP与排查实战

Java后端必懂的网络基础:分层、TCP/IP、HTTP与排查实战

1. 从一次前后端联调失败说起:为什么Java后端必须懂网络我印象很深,刚带团队那会儿,有个刚入职的同事调接口,前端说"连不上后端",后端说"我明明启动了",两边都是新手,在群里…

2026/9/13 23:08:05 阅读更多 →
其域lcc2丢失部分lod/远处显示空洞的解决方式

其域lcc2丢失部分lod/远处显示空洞的解决方式

遇上个麻烦问题,在unity中lcc2模型某些位置离远了就不显示了。推测是只剩下了lod0,lod1-lod10丢失了。折腾了挺久,客服也不太懂,然后发现个简单的解决方式,在LCC Model Editor导出成PLY格式,然后导入再重新导出lcc2,就…

2026/9/13 23:08:05 阅读更多 →
自带降重+降 AI 率功能!2026这3款降AI率软件太省心了!

自带降重+降 AI 率功能!2026这3款降AI率软件太省心了!

谁还在为AI生成论文的AI率太高发愁?明明用AI省了时间,结果查重时AIGC率超标,直接被老师打回重写,熬夜改到崩溃真的太窒息了!最近被问最多的就是“有没有可以自动降AI率的论文生成工具”,作为过来人&#xf…

2026/9/13 23:07:04 阅读更多 →

日新闻

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/13 0:00:24 阅读更多 →
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/13 0:00:24 阅读更多 →
Flutter应用改名全指南:从Android到iOS的配置与工具实践

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

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

2026/9/13 0:00:24 阅读更多 →

周新闻

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/13 0:00:24 阅读更多 →
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/13 0:00:24 阅读更多 →
Flutter应用改名全指南:从Android到iOS的配置与工具实践

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

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

2026/9/13 0:00:24 阅读更多 →

月新闻

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

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

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

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

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

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

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

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

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

2026/9/12 19:02:44 阅读更多 →