Recipes#
This page includes code snippets or “recipes” for a variety of common tasks. Use them as building blocks or examples when making your own notebooks.
In these recipes, each code block represents a cell.
Control Flow#
Show an output conditionally#
Use cases. Hide an output until a condition is met (e.g., until algorithm parameters are valid), or show different outputs depending on the value of a UI element or some other Python object
Recipe.
Use an
if
expression to choose which output to show.
# condition is a boolean, True of False
condition = True
"condition is True" if condition else None
Run a cell on a timer#
Use cases.
Load new data periodically, and show updated plots or other outputs. For example, in a dashboard monitoring a training run, experiment trial, real-time weather data, …
Run a job periodically
Recipe.
Import packages
import marimo as mo
Create a
mo.ui.refresh
timer that fires once a second:
refresh = mo.ui.refresh(default_interval="1s")
# This outputs a timer that fires once a second
refresh
Reference the timer by name to make this cell run once a second
import random
# This cell will run once a second!
refresh
mo.md("#" + "🍃" * random.randint(1, 10))
Require form submission before sending UI value#
Use cases. UI elements automatically send their values to the Python when they are interacted with, and run all cells referencing the elements. This makes marimo notebooks responsive, but it can be an issue when the downstream cells are expensive, or when the input (such as a text box) needs to be filled out completely before it is considered valid. Forms let you gate submission of UI element values on manual confirmation, via a button press.
Recipe.
Import packages
import marimo as mo
Create a submittable form.
form = mo.ui.text(label="Your name").form()
form
Get the value of the form.
form.value
Stop execution of a cell and its descendants#
Use cases. For example, don’t run a cell or its descendants if a form is unsubmitted.
Recipe.
Import packages
import marimo as mo
Create a submittable form.
form = mo.ui.text(label="Your name").form()
form
Use
mo.stop
to stop execution when the form is unsubmitted.
mo.stop(form.value is None, mo.md("Submit the form to continue"))
mo.md(f"Hello, {form.value}!")
Grouping UI elements together#
Create an array of UI elements#
Use cases. In order to synchronize UI elements between the frontend and backend (Python), marimo requires you to assign UI elements to global variables. But sometimes you don’t know the number of elements to make until runtime: for example, maybe you want o make a list of sliders, and the number of sliders to make depends on the value of some other UI element.
You might be tempted to create a Python list of UI elements,
such as l = [mo.ui.slider(1, 10) for i in range(number.value)]
: however,
this won’t work, because the sliders are not bound to global variables.
For such cases, marimo provides the “higher-order” UI element
mo.ui.array
, which lets you make
a new UI element out of a list of UI elements:
l = mo.ui.array([mo.ui.slider(1, 10) for i in range(number.value)])
.
The value of an array
element is a list of the values of the elements
it wraps (in this case, a list of the slider values). Any time you interact
with any of the UI elements in the array, all cells referencing the array
by name (in this case, “l
”) will run automatically.
Recipe.
Import packages.
import marimo as mo
Use
mo.ui.array
to group together many UI elements into a list.
import random
# instead of random.randint, in your notebook you'd use the value of
# an upstream UI element or other Python object
array = mo.ui.array([mo.ui.text() for i in range(random.randint(1, 10))])
array
Get the value of the UI elements using
array.value
array.value
Create a dictionary of UI elements#
Use cases. Same as for creating an array of UI elements, but lets you name each of the wrapped elements with a string key.
Recipe.
Import packages.
import marimo as mo
Use
mo.ui.dictionary
to group together many UI elements into a list.
import random
# instead of random.randint, in your notebook you'd use the value of
# an upstream UI element or other Python object
dictionary = mo.ui.dictionary({str(i): mo.ui.text() for i in range(random.randint(1, 10))})
dictionary
Get the value of the UI elements using
dictionary.value
dictionary.value
Create a batch of UI elements with custom formatting#
Use cases. When you want to batch UI elements together into a dictionary
,
but want custom formatting, use Html.batch
or mo.ui.batch
.
Recipe.
Import packages
import marimo as mo
Create an HTML template, and use
Html.batch
to interpolate UI elements into it to create a new UI element batching the constituent ones (likemo.ui.dictionary
).
# n_items, checkboxes, and texts are just example data: replace them
# with the real data you want to put in the batch
import random
n_items = random.randint(1, 10)
checkboxes = {f"checkbox_{i}": mo.ui.checkbox() for i in range(n_items)}
texts = {
f"text_{i}": mo.ui.text(placeholder="task ...") for i in range(n_items)
}
# a utility function that creates a placeholder that will be substituted
# for a UI element
def _placeholder(name) -> str:
return "{" + name + "}"
# A batch is just like mo.ui.dictionary(), but lets you have custom formatting.
#
# To use batch, first create an HTML object with placeholders for
# the UI elements. A placeholder is a string key closed in braces,
# such as "{my_button}".
#
# Then, call `batch()` with keys equal to placeholder
# names and values equal to the UI elements you want to substitute, such as
# `.batch(my_button=mo.ui.button())`.
#
# If you have many placeholders, create a dict with the placeholders as keys
# and their UI elements as values, and unpack them when you call batch:
# `.batch(**placeholders_and_values)`.
batch = mo.md(
f"""
Here's a TODO list of {n_items} items\n\n
"""
+ "\n\n".join(
[
_placeholder(checkbox_key) + " " + _placeholder(text_key)
for checkbox_key, text_key in zip(checkboxes.keys(), texts.keys())
]
)
).batch(**checkboxes, **texts)
batch
Get the value of the batch as a Python
dict
, with placeholders as keys and their UI element values as values.
batch.value
Create a vstack (or hstack) of UI elements with on_change
handlers#
Use cases. Arrange a dynamic number of UI elements in a vstack or hstack, for example some number of buttons, and execute some side-effect when an element is interacted with, e.g. when a button is clicked.
Recipe.
Import packages
import marimo as mo
Create an HTML template, and use
Html.batch
to interpolate UI elements into it to create a new UI element batching the constituent ones (likemo.ui.dictionary
).
import random
def on_change(v):
# replace with your code
...
# create a dictionary of your UI elements, keyed by placeholder names
buttons = {
f"button_{i}": mo.ui.button(label=i, on_change=on_change)
for i in range(random.randint(3, 10)
}
# a utility function that creates a placeholder that will be substituted
# for a UI element
def _placeholder(name) -> str:
return "{" + name + "}"
# A batch is just like mo.ui.dictionary(), but lets you have custom formatting.
#
# To use batch, first create an HTML object with placeholders for
# the UI elements. A placeholder is a string key closed in braces,
# such as "{my_button}".
#
# Then, call `batch()` with keys equal to placeholder
# names and values equal to the UI elements you want to substitute, such as
# `.batch(my_button=mo.ui.button())`.
#
# If you have many placeholders, create a dict with the placeholders as keys
# and their UI elements as values, and unpack them when you call batch:
# `.batch(**placeholders_and_values)`.
batch = mo.vstack([
_placeholder(name) for name in buttons.keys()
]).batch(**buttons)
# Output the batched vstack
batch
Get the value of the batch as a Python
dict
, with placeholders as keys and their UI element values as values.
batch.value
Create a form with multiple UI elements#
Use cases. Combine multiple UI elements into a form so that submission of the form sends all its elements to Python.
Recipe.
Import packages.
import marimo as mo
Use
mo.ui.form
andHtml.batch
to create a form with multiple elements.
form = mo.md(
r"""
Choose your algorithm parameters:
- $\epsilon$: {epsilon}
- $\delta$: {delta}
"""
).batch(epsilon=mo.ui.slider(0.1, 1, step=0.1), delta=mo.ui.number(1, 10)).form()
form
Get the submitted form value.
form.value
Caching#
Cache expensive computations#
Use case. Because marimo runs cells automatically as code and UI elements change, it can be helpful to cache expensive intermediate computations. For example, perhaps your notebook computes t-SNE, UMAP, or PyMDE embeddings, and exposes their parameters as UI elements. Caching the embeddings for different configurations of the elements would greatly speed up your notebook.
Recipe.
Use
functools
to cache function outputs given inputs.
import functools
@functools.cache
def compute_predictions(problem_parameters):
# replace with your own function/parameters
...
Whenever compute_predictions
is called with a value of problem_parameters
it has not seen, it will compute the predictions and store them in a cache. The
next time it is called with the same parameters, instead of recomputing the
predictions, it will return the previously computed value from the cache.
See our best practices guide to learn more.