知识广场
按学科筛选:计算机科学 / 机器学习 / 数据科学
«计算机科学 / 机器学习 / 数据科学» 分类下共 1 篇帖子
## 起因 Jupyter notebook 用了 10 年,痛点积累: - cell 乱序执行 → 隐藏状态 / 难复现 - JSON 文件 git diff 不友好 - 无 IDE 类型检查 - 不能直接 run as script - import 难(要把 notebook 转 .py) `marimo`(2023+)是新一代 Python notebook,**reactive** 设计: - 单 file = `.py`(git friendly + 可 import) - cell dependency 图 → 改一个 cell 自动重跑下游 - 无隐藏状态(重启 → 一致结果) - 内置 UI widget(slider / dropdown 等) ## 装 ```bash pip install marimo # 或者 uv add marimo ``` ```bash marimo new # 新建 notebook marimo edit my.py # 编辑 marimo run my.py # 当 app 跑(read-only) ``` ## 文件格式 ```python # my_notebook.py import marimo __generated_with = "0.6.0" app = marimo.App() @app.cell def __(): import polars as pl df = pl.read_csv('data.csv') df @app.cell def __(df): summary = df.group_by('country').agg(pl.col('amount').sum()) summary @app.cell def __(summary): summary.plot.bar(x='country', y='amount') ``` 每 cell 是函数:参数 = 它依赖的变量。 marimo 自动构建 DAG,运行时知道改 `df` → `summary` 重算 → `plot` 重算。 ## reactivity 改第一个 cell,比如 `pl.read_csv('other.csv')`: - marimo 自动识别 `df` 变了 - 下游 cell(用 `df` 的)自动跑 - 不用手动 Shift+Enter 每个 cell vs Jupyter:你必须记得"我改了 df,要 re-run 下游"。少 re-run 一个就 state 不一致。 ## 无隐藏状态 Jupyter 经典 bug: ```python # cell 1 x = 5 # cell 2 print(x) # 5 # cell 1 修改 x = 10 # 不重跑 cell 2 # cell 3 print(x) # 10 # cell 2 显示 5,cell 3 显示 10 → 矛盾状态 ``` marimo 不允许:cell 1 改了 → cell 2 / 3 都重跑。 restart kernel + run all 跟正常 run 一样。 ## git friendly ```bash $ git diff my_notebook.py - df = pl.read_csv('data.csv') + df = pl.read_csv('orders.csv') ``` 正常 Python diff。 vs Jupyter `.ipynb`: ```bash $ git diff my.ipynb - "execution_count": 12, + "execution_count": 13, - "metadata": {"id": "abc"}, + "metadata": {"id": "def"}, - ... 几百行 base64 image diff ``` `.ipynb` 是 JSON + base64 编码的 output,PR review 痛苦。 工具如 `nbdime` / `jupytext` 能缓解但 marimo 原生 .py 更纯。 ## 当 script 跑 ```bash python my_notebook.py # 跟 jupyter nbconvert 不一样,marimo .py 真的是 Python 文件,直接跑 ``` CI 跑 notebook 测试 → 一行命令。 ## 当 import 用 ```python # main.py from my_notebook import summary # marimo 让 cell 变量 import 出来 ``` marimo notebook = Python module。 prototype 完直接被生产 code 引用,不用"先把 cell 改 function 再 import"。 ## UI widget ```python @app.cell def __(mo): slider = mo.ui.slider(0, 100, value=50, label='Sample size') slider @app.cell def __(slider, df): sample = df.head(slider.value) sample ``` slider 调 → 自动重算 sample → 显新结果。 不用 ipywidgets 复杂 callback。 ## marimo as app ```bash marimo run my.py --host 0.0.0.0 --port 8000 ``` 变成 web app(read-only),URL 分享给同事。 UI widget 仍可交互。 替代 streamlit 简单场景。 ## vs Jupyter 优势汇总 | | Jupyter | marimo | |---|---|---| | 文件格式 | JSON .ipynb | Python .py | | 隐藏状态 | 是 | 否 | | Reactive | 否 | 是 | | Git diff | 烂 | 好 | | Run as script | 要 nbconvert | 直接 | | Import | 要 nbconvert | 直接 | | UI widget | ipywidgets | marimo.ui | | AI 友好度 | 弱(JSON) | 强(.py) | ## Jupyter 仍胜的场景 - 巨大社区(教程 / 大量 .ipynb 内容) - Google Colab / Kaggle / VS Code 内置 Jupyter - 自由 cell 顺序(marimo 强制 DAG 无环) - 显示 rich output 历史悠久 + 稳 新项目我用 marimo,老 .ipynb 继续 Jupyter。 ## 我的工作流 数据探索: 1. `marimo edit explore.py` 2. 改 cell → 即时看下游结果(reactive) 3. 完成的 cell 重构成 function 4. 把 explore.py 里关键 function `import` 到 production code production analysis dashboard: 1. `marimo edit dashboard.py` 加 widget 2. `marimo run dashboard.py --headless` 部署 替代 Jupyter + nbconvert + streamlit 三个工具。 ## 与 nbdev 对比 `nbdev`(fast.ai):Jupyter 当源码,notebook 直接 ship 为库。 marimo:notebook 就是 .py,本来就是源码。 nbdev 改进 Jupyter;marimo 重新设计。我选 marimo(少抽象层)。 ## 与 Pluto.jl 对比 Julia 的 Pluto 是 marimo 的灵感来源(reactive notebook)。 marimo 在 Python 把这模型实现。 ## 性能 reactive DAG 计算开销小(几 ms / 改动)。 大 cell 仍跟 Jupyter 一样跑。 增量执行有时还更快(只跑变化的 cell + 下游)。 ## 踩过的坑 1. **强制 DAG 无环**:写 `x = 1` in cell 1 + `x = 2` in cell 2 报错 (same variable defined twice)。需要 refactor 到 function 或者 rename。开始不适应。 2. **某些 imperative pattern 不支持**:`for i in range(5): print(i)` in cell → marimo 不 reactive。包 function。 3. **plot library 兼容**:matplotlib OK;plotly / altair OK; 极少 niche lib 可能不渲染。 4. **AI tab completion 弱于 Jupyter**:jupyter-ai / VS Code Copilot Jupyter 集成强。marimo 在追赶。 5. **大 dataframe display 慢**:reactive 每次跑都重 display。 `df` 大时显式 `df.head()`,或者 cache。