跳转至

Marimo 反应式 Python 笔记本

一句话说明: Marimo 是 Jupyter 的现代替代品,采用反应式执行模型(修改一个单元格自动更新所有依赖单元格),且笔记本就是纯 .py 文件,天然支持版本控制。


为什么要学

  1. 反应式执行 — 修改变量自动级联更新依赖单元格,消除隐藏状态 bug
  2. 纯 Python 文件.py 格式存储,git diff 友好,不再有 JSON notebook 的合并噩梦
  3. 内置交互组件 — slider、dropdown、table 等 UI 组件开箱即用
  4. 可部署为应用 — 笔记本可一键导出为交互式 Web App
  5. 确定性执行 — DAG 依赖图保证执行顺序确定,不依赖单元格位置

核心概念详解

与 Jupyter 对比

特性MarimoJupyter
执行模型反应式(DAG)手动顺序执行
文件格式.py(纯 Python).ipynb(JSON)
隐藏状态不可能产生常见陷阱
Git 友好原生友好需要 nbstripout 等工具
交互组件内置需 ipywidgets
部署为 App原生支持需 Voila/Panel
变量重定义禁止(编译检查)允许(易出错)

反应式模型

Cell A: x = 5
Cell B: y = x * 2      ← 依赖 A
Cell C: z = y + 1      ← 依赖 B

修改 Cell A 中 x = 10 → Cell B 自动重算 y = 20 → Cell C 自动重算 z = 21

核心规则

  1. 每个变量只能在一个单元格中定义 — 消除歧义
  2. 单元格之间通过变量名隐式连接 — 形成 DAG
  3. 不存在执行顺序依赖 — 只有数据依赖
  4. 删除单元格会清除其定义的变量 — 状态始终一致

安装与配置

安装

# pip
pip install marimo

# uv(推荐)
uv pip install marimo

# conda
conda install -c conda-forge marimo

启动

# 创建新笔记本
marimo edit

# 编辑已有笔记本
marimo edit notebook.py

# 以应用模式运行(只读交互)
marimo run notebook.py

# 指定端口
marimo edit --port 8080

VS Code 集成

安装 Marimo 官方 VS Code 扩展,支持在编辑器内运行。

验证

marimo --version
# marimo 0.10.0

快速上手

创建第一个笔记本

marimo edit hello.py

在浏览器中打开后,创建单元格:

# Cell 1
import marimo as mo
# Cell 2
import numpy as np
import matplotlib.pyplot as plt
# Cell 3 - 交互组件
slider = mo.ui.slider(1, 100, value=50, label="样本数量")
slider
# 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
# 获取用户选中的行
selected = table.value
mo.md(f"选中了 {len(selected)} 行")

3. 条件显示与布局

import marimo as mo

tabs = mo.ui.tabs({
    "数据": mo.md("数据展示区域"),
    "图表": mo.md("图表展示区域"),
    "设置": mo.md("配置区域"),
})
tabs
# 水平/垂直/网格布局
mo.hstack([chart1, chart2], justify="space-around")
mo.vstack([header, body, footer])

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 迁移

# 转换 .ipynb 为 marimo .py
marimo convert notebook.ipynb -o notebook.py

7. 环境管理(内联依赖)

# 笔记本顶部声明依赖
app = marimo.App()

# marimo 支持 uv 自动安装依赖
# /// script
# dependencies = ["pandas", "matplotlib", "scikit-learn"]
# ///

常见问题与排错

Q: "变量 X 在多个单元格中定义"

Marimo 要求每个变量只能在一个单元格中赋值。解决方案: - 合并相关单元格 - 使用不同变量名 - 用函数封装逻辑

Q: 如何使用全局变量/常量

# 在一个 cell 中定义所有常量
CONFIG = {"batch_size": 32, "lr": 0.001}

Q: 反应式执行太频繁/太慢

# 使用 run_button 控制执行时机
btn = mo.ui.run_button(label="执行分析")
btn

# 只有点击按钮后才执行
mo.stop(not btn.value, "点击按钮开始分析")
# 下面的代码只在按钮点击后执行
result = expensive_computation()

Q: 如何与已有 Python 项目集成

Marimo 笔记本就是 .py 文件,可以直接 import 项目模块:

from my_project.models import train_model
from my_project.data import load_dataset

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