marimo-notebook

marimo-notebook

熱門

以正確格式在 Python 檔案中撰寫 marimo 筆記本。

157星標
14分支
更新於 2026/6/15
SKILL.md
唯讀
名稱
marimo-notebook
描述

以正確格式在 Python 檔案中撰寫 marimo 筆記本。

marimo 筆記本注意事項

marimo 使用 Python 建立筆記本,不同於 Jupyter 使用 JSON。以下是一個範例筆記本:

# /// script
# dependencies = [
#     "marimo",
#     "numpy==2.4.3",
# ]
# requires-python = ">=3.14"
# ///

import marimo

__generated_with = "0.20.4"
app = marimo.App(width="medium")


@app.cell
def _():
    import marimo as mo
    import numpy as np

    return mo, np


@app.cell
def _():
    print("hello world")
    return


@app.cell
def _(np, slider):
    np.array([1,2,3]) + slider.value
    return


@app.cell
def _(mo):
    slider = mo.ui.slider(1, 10, 1, label="要加的數字")
    slider
    return (slider,)


@app.cell
def _():
    return


if __name__ == "__main__":
    app.run()

請注意,筆記本以函式結構呈現,每個函式代表一個儲存格的內容。每個儲存格使用 @app.cell 裝飾器定義,函式的輸入/輸出即為儲存格的輸入/輸出。marimo 通常會自動處理儲存格之間的依賴關係。

執行 marimo 筆記本

# 以腳本方式執行(非互動式,用於測試)
uv run <notebook.py>

# 在瀏覽器中互動式執行
uv run marimo run <notebook.py>

# 互動式編輯
uv run marimo edit <notebook.py>

腳本模式偵測

使用 mo.app_meta().mode == "script" 來區分 CLI 與互動模式:

@app.cell
def _(mo):
    is_script_mode = mo.app_meta().mode == "script"
    return (is_script_mode,)

關鍵原則:保持簡單

永遠顯示所有 UI 元素。 只在腳本模式下變更資料來源。

  • 滑桿、按鈕、小工具應始終建立並顯示
  • 在腳本模式下,只需使用合成/預設資料,而非等待使用者輸入
  • 不要將所有東西包在 if not is_script_mode 條件中
  • 不要使用 try/except 處理正常流程

良好範例

# 永遠顯示小工具
@app.cell
def _(ScatterWidget, mo):
    scatter_widget = mo.ui.anywidget(ScatterWidget())
    scatter_widget
    return (scatter_widget,)

# 僅根據模式變更資料來源
@app.cell
def _(is_script_mode, make_moons, scatter_widget, np, torch):
    if is_script_mode:
        # 使用合成資料進行測試
        X, y = make_moons(n_samples=200, noise=0.2)
        X_data = torch.tensor(X, dtype=torch.float32)
        y_data = torch.tensor(y)
        data_error = None
    else:
        # 在互動模式下使用小工具資料
        X, y = scatter_widget.widget.data_as_X_y
        # ... 處理資料 ...
    return X_data, y_data, data_error

# 永遠顯示滑桿 - 在兩種模式下都使用 .value
@app.cell
def _(mo):
    lr_slider = mo.ui.slider(start=0.001, stop=0.1, value=0.01)
    lr_slider
    return (lr_slider,)

# 腳本模式下自動執行,互動模式下等待按鈕
@app.cell
def _(is_script_mode, train_button, lr_slider, run_training, X_data, y_data):
    if is_script_mode:
        # 使用滑桿預設值自動執行
        results = run_training(X_data, y_data, lr=lr_slider.value)
    else:
        # 等待按鈕點擊
        if train_button.value:
            results = run_training(X_data, y_data, lr=lr_slider.value)
    return (results,)

狀態與反應性

儲存格之間的變數定義了筆記本的反應性,適用於 99% 的使用案例。不需要特殊的狀態管理。不要在儲存格間變動物件(例如 my_list.append());請建立新物件。除非需要雙向 UI 同步或累積回呼狀態,否則避免使用 mo.state()。詳見 STATE.md

不要用 if 語句保護儲存格

Marimo 的反應性意味著儲存格僅在其依賴項就緒時才會執行。不要添加不必要的保護:

# 錯誤 - if 語句阻止圖表顯示
@app.cell
def _(plt, training_results):
    if training_results:  # 錯誤 - 不要這樣做
        fig, ax = plt.subplots()
        ax.plot(training_results['losses'])
        fig
    return

# 正確 - 讓 marimo 處理依賴關係
@app.cell
def _(plt, training_results):
    fig, ax = plt.subplots()
    ax.plot(training_results['losses'])
    fig
    return

該儲存格在 training_results 有值之前不會執行。

不要使用 try/except 控制流程

除非處理特定、預期的例外,否則不要將程式碼包在 try/except 區塊中。讓錯誤自然顯現。

# 錯誤 - 用 try/except 隱藏錯誤
@app.cell
def _(scatter_widget, np, torch):
    try:
        X, y = scatter_widget.widget.data_as_X_y
        X = np.array(X, dtype=np.float32)
        # ...
    except Exception as e:
        return None, None, f"錯誤:{e}"

# 正確 - 如果有問題就讓它失敗
@app.cell
def _(scatter_widget, np, torch):
    X, y = scatter_widget.widget.data_as_X_y
    X = np.array(X, dtype=np.float32)
    # ...

僅在以下情況使用 try/except:

  • 處理特定、已知的例外類型
  • 例外在正常操作中可預期(例如檔案未找到)
  • 有有意義的復原動作

儲存格輸出渲染

Marimo 僅渲染儲存格的最終表達式。縮排或條件表達式不會渲染:

# 錯誤 - 縮排表達式不會渲染
@app.cell
def _(mo, condition):
    if condition:
        mo.md("這不會顯示!")  # 錯誤 - 縮排
    return

# 正確 - 最終表達式會渲染
@app.cell
def _(mo, condition):
    result = mo.md("顯示!") if condition else mo.md("也顯示!")
    result  # 因為是最終表達式,所以會渲染
    return

PEP 723 依賴項

透過 marimo edit --sandbox 建立的筆記本會自動在檔案頂部加入這些依賴項,但建立筆記本時也建議確保它們存在:

# /// script
# requires-python = ">=3.12"
# dependencies = [
#     "marimo",
#     "torch>=2.0.0",
# ]
# ///

marimo check

處理筆記本時,檢查筆記本是否能執行很重要。因此 marimo 提供了 check 命令,作為 linter 來找出常見錯誤。

uvx marimo check <notebook.py>

在將筆記本交給使用者之前,請確保已執行這些檢查。

重要:你傾向於過度使用底線前綴的變數。最多只對一兩個變數這樣做。考慮建立新變數,而不是在 marimo 中為整個儲存格加上前綴。

API 文件

如果使用者特別要求使用某個 marimo 函式,你可以透過以下方式在本機查閱文件:

uv --with marimo run python -c "import marimo as mo; help(mo.ui.form)"

測試

預設情況下,marimo 會在你的筆記本中發現並執行測試。
當可選的 pytest 依賴項存在時,marimo 會在僅包含測試程式碼的儲存格上執行 pytest——即函式名稱以 test_ 開頭的函式。
如果使用者要求你加入測試,請確保加入 pytest 依賴項,並且有一個僅包含測試程式碼的儲存格。

更多關於使用 pytest 測試的資訊,請參閱 PYTEST.md

加入測試後,你可以從命令列對筆記本執行 pytest。

pytest <notebook.py>

其他資源

  • 關於寬度為 columns 的 marimo 筆記本:SQL.md
  • 關於 marimo 中的 SQL 使用:SQL.md
  • 關於 marimo 中的 UI 元素:UI.md
  • 關於將函式/類別暴露為頂層匯入:TOP-LEVEL-IMPORTS.md
  • 關於匯出筆記本(PDF、HTML、markdown 等):EXPORTS.md
  • 關於狀態管理與反應性:STATE.md
  • 關於 marimo 筆記本的部署:DEPLOYMENT.md
  • 關於使用 anywidget 的自訂互動小工具:ANYWIDGET.md
  • 關於外部編輯與 --watch 模式:WATCHING.md
  • 關於耗費資源的筆記本(快取、惰性求值、mo.stop):EXPENSIVE.md
  • 關於設定(pyproject.toml、marimo.toml):CONFIGURATION.md
  • 關於反應性模型(DAG、變數作用域、變異):REACTIVITY.md