Marimo 反应式 Python 笔记本¶
一句话说明: Marimo 是 Jupyter 的现代替代品,采用反应式执行模型(修改一个单元格自动更新所有依赖单元格),且笔记本就是纯
.py文件,天然支持版本控制。
为什么要学¶
- 反应式执行 — 修改变量自动级联更新依赖单元格,消除隐藏状态 bug
- 纯 Python 文件 —
.py格式存储,git diff 友好,不再有 JSON notebook 的合并噩梦 - 内置交互组件 — slider、dropdown、table 等 UI 组件开箱即用
- 可部署为应用 — 笔记本可一键导出为交互式 Web App
- 确定性执行 — DAG 依赖图保证执行顺序确定,不依赖单元格位置
核心概念详解¶
与 Jupyter 对比¶
| 特性 | Marimo | Jupyter |
|---|---|---|
| 执行模型 | 反应式(DAG) | 手动顺序执行 |
| 文件格式 | .py(纯 Python) | .ipynb(JSON) |
| 隐藏状态 | 不可能产生 | 常见陷阱 |
| Git 友好 | 原生友好 | 需要 nbstripout 等工具 |
| 交互组件 | 内置 | 需 ipywidgets |
| 部署为 App | 原生支持 | 需 Voila/Panel |
| 变量重定义 | 禁止(编译检查) | 允许(易出错) |
反应式模型¶
修改 Cell A 中 x = 10 → Cell B 自动重算 y = 20 → Cell C 自动重算 z = 21
核心规则¶
- 每个变量只能在一个单元格中定义 — 消除歧义
- 单元格之间通过变量名隐式连接 — 形成 DAG
- 不存在执行顺序依赖 — 只有数据依赖
- 删除单元格会清除其定义的变量 — 状态始终一致
安装与配置¶
安装¶
启动¶
# 创建新笔记本
marimo edit
# 编辑已有笔记本
marimo edit notebook.py
# 以应用模式运行(只读交互)
marimo run notebook.py
# 指定端口
marimo edit --port 8080
VS Code 集成¶
安装 Marimo 官方 VS Code 扩展,支持在编辑器内运行。
验证¶
快速上手¶
创建第一个笔记本¶
在浏览器中打开后,创建单元格:
# Cell 4 - 反应式更新
data = np.random.randn(slider.value)
fig, ax = plt.subplots()
ax.hist(data, bins=20)
ax.set_title(f"正态分布 (n={slider.value})")
plt.gca()
拖动 slider → 直方图自动更新。
文件内容(纯 Python)¶
保存后的 hello.py 是标准 Python 文件:
import marimo
__generated_with = "0.10.0"
app = marimo.App()
@app.cell
def _():
import marimo as mo
return (mo,)
@app.cell
def _(mo):
slider = mo.ui.slider(1, 100, value=50, label="样本数量")
slider
return (slider,)
@app.cell
def _(np, plt, slider):
data = np.random.randn(slider.value)
fig, ax = plt.subplots()
ax.hist(data, bins=20)
ax.set_title(f"正态分布 (n={slider.value})")
plt.gca()
return (ax, data, fig)
if __name__ == "__main__":
app.run()
进阶用法¶
1. 丰富的 UI 组件¶
import marimo as mo
# 下拉选择
dataset = mo.ui.dropdown(
options=["iris", "wine", "digits"],
value="iris",
label="选择数据集"
)
# 多选
features = mo.ui.multiselect(
options=["sepal_length", "sepal_width", "petal_length", "petal_width"],
label="选择特征"
)
# 文本输入
query = mo.ui.text(placeholder="输入搜索关键词...")
# 按钮
run_btn = mo.ui.run_button(label="开始分析")
# 组合展示
mo.vstack([dataset, features, query, run_btn])
2. 交互式表格¶
import marimo as mo
import pandas as pd
df = pd.DataFrame({
"基因": ["TP53", "BRCA1", "EGFR", "KRAS"],
"表达量": [12.5, 8.3, 15.7, 6.2],
"显著性": [0.001, 0.05, 0.003, 0.12],
})
# 可筛选、排序、选择行的交互表格
table = mo.ui.table(df, selection="multi")
table
3. 条件显示与布局¶
import marimo as mo
tabs = mo.ui.tabs({
"数据": mo.md("数据展示区域"),
"图表": mo.md("图表展示区域"),
"设置": mo.md("配置区域"),
})
tabs
4. SQL 集成¶
import marimo as mo
# 内置 SQL 支持
result = mo.sql(f"""
SELECT gene, expression, pvalue
FROM df
WHERE pvalue < 0.05
ORDER BY expression DESC
""")
result
5. 部署为 Web 应用¶
# 应用模式(隐藏代码,只展示输出和交互)
marimo run analysis.py --host 0.0.0.0 --port 8080
# 导出为静态 HTML
marimo export html notebook.py -o output.html
# 导出为 WASM(纯前端运行)
marimo export html --mode wasm notebook.py -o app.html
6. 从 Jupyter 迁移¶
7. 环境管理(内联依赖)¶
# 笔记本顶部声明依赖
app = marimo.App()
# marimo 支持 uv 自动安装依赖
# /// script
# dependencies = ["pandas", "matplotlib", "scikit-learn"]
# ///
常见问题与排错¶
Q: "变量 X 在多个单元格中定义"¶
Marimo 要求每个变量只能在一个单元格中赋值。解决方案: - 合并相关单元格 - 使用不同变量名 - 用函数封装逻辑
Q: 如何使用全局变量/常量¶
Q: 反应式执行太频繁/太慢¶
# 使用 run_button 控制执行时机
btn = mo.ui.run_button(label="执行分析")
btn
# 只有点击按钮后才执行
mo.stop(not btn.value, "点击按钮开始分析")
# 下面的代码只在按钮点击后执行
result = expensive_computation()
Q: 如何与已有 Python 项目集成¶
Marimo 笔记本就是 .py 文件,可以直接 import 项目模块:
Q: 怎么在笔记本中运行 shell 命令¶
import subprocess
result = subprocess.run(["ls", "-la"], capture_output=True, text=True)
mo.md(f"```\n{result.stdout}\n```")
参考资源¶
- 官方文档:https://docs.marimo.io
- GitHub 仓库:https://github.com/marimo-team/marimo
- 在线 Playground:https://marimo.app
- 示例库:https://marimo.io/gallery
- Discord 社区:https://discord.gg/JE7nhX6mD8
- 从 Jupyter 迁移:https://docs.marimo.io/guides/coming_from/jupyter.html