以正確格式在 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






