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
Embed a dynamic number of UI elements in another output#
Use cases. When you want to embed a dynamic number of UI elements in other outputs (like tables or markdown).
Recipe.
Import packages
import marimo as mo
Group the elements with
mo.ui.dictionary
ormo.ui.array
, then retrieve them from the container and display them elsewhere.
import random
n_items = random.randint(2, 5)
# Create a dynamic number of elements using `mo.ui.dictionary` and
# `mo.ui.array`
elements = mo.ui.dictionary(
{
"checkboxes": mo.ui.array([mo.ui.checkbox() for _ in range(n_items)]),
"texts": mo.ui.array(
[mo.ui.text(placeholder="task ...") for _ in range(n_items)]
),
}
)
mo.md(
f"""
Here's a TODO list of {n_items} items\n\n
"""
+ "\n\n".join(
# Iterate over the elements and embed them in markdown
[
f"{checkbox} {text}"
for checkbox, text in zip(
elements["checkboxes"], elements["texts"]
)
]
)
)
Get the value of the elements
elements.value
Create a hstack (or vstack) of UI elements with on_change
handlers#
Use cases. Arrange a dynamic number of UI elements in a hstack or vstack, 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 buttons in
mo.ui.array
and pass them to hstack – a regular Python list won’t work. Make sure to assign the array to a global variable.
import random
# Create a state object that will store the index of the
# clicked button
get_state, set_state = mo.state(None)
# Create an mo.ui.array of buttons - a regular Python list won't work.
buttons = mo.ui.array(
[
mo.ui.button(
label="button " + str(i), on_change=lambda v, i=i: set_state(i)
)
for i in range(random.randint(2, 5))
]
)
mo.hstack(buttons)
Get the state value
get_state()
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.