marimo-notebook

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Notes for marimo Notebooks

marimo笔记本编写注意事项

Running Marimo Notebooks

运行marimo笔记本

bash
undefined
bash
undefined

Run as script (non-interactive, for testing)

以脚本模式运行(非交互式,用于测试)

uv run <notebook.py>
uv run <notebook.py>

Run interactively in browser

在浏览器中交互式运行

uv run marimo run <notebook.py>
uv run marimo run <notebook.py>

Edit interactively

交互式编辑

uv run marimo edit <notebook.py>
undefined
uv run marimo edit <notebook.py>
undefined

Script Mode Detection

脚本模式检测

Use
mo.app_meta().mode == "script"
to detect CLI vs interactive:
python
@app.cell
def _(mo):
    is_script_mode = mo.app_meta().mode == "script"
    return (is_script_mode,)
使用
mo.app_meta().mode == "script"
来检测是CLI模式还是交互式模式:
python
@app.cell
def _(mo):
    is_script_mode = mo.app_meta().mode == "script"
    return (is_script_mode,)

Key Principle: Keep It Simple

核心原则:保持简洁

Show all UI elements always. Only change the data source in script mode.
  • Sliders, buttons, widgets should always be created and displayed
  • In script mode, just use synthetic/default data instead of waiting for user input
  • Don't wrap everything in
    if not is_script_mode
    conditionals
  • Don't use try/except for normal control flow
始终显示所有UI元素。仅在脚本模式下更改数据源。
  • 滑块、按钮、小部件应始终创建并显示
  • 在脚本模式下,只需使用模拟/默认数据,无需等待用户输入
  • 不要将所有内容都包裹在
    if not is_script_mode
    条件判断中
  • 不要在常规控制流中使用try/except

Good Pattern

良好实践

python
undefined
python
undefined

Always show the widget

始终显示小部件

@app.cell def _(ScatterWidget, mo): scatter_widget = mo.ui.anywidget(ScatterWidget()) scatter_widget return (scatter_widget,)
@app.cell def _(ScatterWidget, mo): scatter_widget = mo.ui.anywidget(ScatterWidget()) scatter_widget return (scatter_widget,)

Only change data source based on mode

仅根据模式更改数据源

@app.cell def _(is_script_mode, make_moons, scatter_widget, np, torch): if is_script_mode: # Use synthetic data for testing 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: # Use widget data in interactive mode X, y = scatter_widget.widget.data_as_X_y # ... process data ... return X_data, y_data, data_error
@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

Always show sliders - use their .value in both modes

始终显示滑块 - 在两种模式下都使用其.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 _(mo): lr_slider = mo.ui.slider(start=0.001, stop=0.1, value=0.01) lr_slider return (lr_slider,)

Auto-run in script mode, wait for button in interactive

脚本模式下自动运行,交互式模式下等待按钮点击

@app.cell def _(is_script_mode, train_button, lr_slider, run_training, X_data, y_data): if is_script_mode: # Auto-run with slider defaults results = run_training(X_data, y_data, lr=lr_slider.value) else: # Wait for button click if train_button.value: results = run_training(X_data, y_data, lr=lr_slider.value) return (results,)
undefined
@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,)
undefined

Don't Guard Cells with
if
Statements

不要用
if
语句包裹单元格

Marimo's reactivity means cells only run when their dependencies are ready. Don't add unnecessary guards:
python
undefined
Marimo的响应式特性意味着单元格仅在其依赖项就绪时才会运行。不要添加不必要的判断:
python
undefined

BAD - the if statement prevents the chart from showing

错误写法 - if语句会阻止图表显示

@app.cell def _(plt, training_results): if training_results: # WRONG - don't do this fig, ax = plt.subplots() ax.plot(training_results['losses']) fig return
@app.cell def _(plt, training_results): if training_results: # 错误 - 不要这样做 fig, ax = plt.subplots() ax.plot(training_results['losses']) fig return

GOOD - let marimo handle the dependency

正确写法 - 让marimo处理依赖关系

@app.cell def _(plt, training_results): fig, ax = plt.subplots() ax.plot(training_results['losses']) fig return

The cell won't run until `training_results` has a value anyway.
@app.cell def _(plt, training_results): fig, ax = plt.subplots() ax.plot(training_results['losses']) fig return

在`training_results`有值之前,单元格不会运行。

Don't Use try/except for Control Flow

不要在控制流中使用try/except

Don't wrap code in try/except blocks unless you're handling a specific, expected exception. Let errors surface naturally.
python
undefined
除非你要处理特定的、可预期的异常,否则不要将代码包裹在try/except块中。让错误自然暴露。
python
undefined

BAD - hiding errors behind 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"Error: {e}"
@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"Error: {e}"

GOOD - let it fail if something is wrong

正确写法 - 如果出现问题就让它报错

@app.cell def _(scatter_widget, np, torch): X, y = scatter_widget.widget.data_as_X_y X = np.array(X, dtype=np.float32) # ...

Only use try/except when:
- You're handling a specific, known exception type
- The exception is expected in normal operation (e.g., file not found)
- You have a meaningful recovery action
@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:
- 你要处理特定的、已知的异常类型
- 该异常在正常操作中是可预期的(例如,文件未找到)
- 你有有意义的恢复措施

Cell Output Rendering

单元格输出渲染

Marimo only renders the final expression of a cell. Indented or conditional expressions won't render:
python
undefined
Marimo仅渲染单元格的最终表达式。缩进或条件中的表达式不会被渲染:
python
undefined

BAD - indented expression won't render

错误写法 - 缩进的表达式不会被渲染

@app.cell def _(mo, condition): if condition: mo.md("This won't show!") # WRONG - indented return
@app.cell def _(mo, condition): if condition: mo.md("这不会显示!") # 错误 - 缩进了 return

GOOD - final expression renders

正确写法 - 最终表达式会被渲染

@app.cell def _(mo, condition): result = mo.md("Shown!") if condition else mo.md("Also shown!") result # This renders because it's the final expression return
undefined
@app.cell def _(mo, condition): result = mo.md("显示内容!") if condition else mo.md("也会显示!") result # 这会被渲染,因为它是最终表达式 return
undefined

Marimo Variable Naming

Marimo变量命名

Variables in
for
loops that would conflict across cells need underscore prefix:
python
undefined
for
循环中,可能会跨单元格冲突的变量需要以下划线前缀:
python
undefined

Use _name, _model to make them cell-private

使用_name, _model使其成为单元格私有变量

for _name, _model in items: ...
undefined
for _name, _model in items: ...
undefined

PEP 723 Dependencies

PEP 723 依赖声明

python
undefined
python
undefined

/// script

/// script

requires-python = ">=3.12"

requires-python = ">=3.12"

dependencies = [

dependencies = [

"marimo",

"marimo",

"torch>=2.0.0",

"torch>=2.0.0",

]

]

///

///

undefined
undefined

Prefer pathlib over os.path

优先使用pathlib而非os.path

Use
pathlib.Path
for file path operations instead of
os.path
:
python
undefined
使用
pathlib.Path
进行文件路径操作,而非
os.path
python
undefined

GOOD - use pathlib

正确写法 - 使用pathlib

from pathlib import Path data_dir = Path(tempfile.mkdtemp()) parquet_file = data_dir / "data.parquet"
from pathlib import Path data_dir = Path(tempfile.mkdtemp()) parquet_file = data_dir / "data.parquet"

BAD - avoid os.path

错误写法 - 避免使用os.path

import os parquet_file = os.path.join(temp_dir, "data.parquet")
undefined
import os parquet_file = os.path.join(temp_dir, "data.parquet")
undefined

marimo check

marimo check命令

When working on a notebook it is important to check if the notebook can run. That's why marimo provides a
check
command that acts as a linter to find common mistakes.
bash
uvx marimo check <notebook.py>
Make sure these are checked before handing a notebook back to the user.
在开发笔记本时,检查笔记本是否能正常运行非常重要。marimo提供了
check
命令,作为代码检查工具来发现常见错误。
bash
uvx marimo check <notebook.py>
在将笔记本交付给用户之前,务必执行这些检查。