Marimo

A python visual notebook that works more like how I imagined jupyter would work when I heard about it

November 4, 2024 — December 18, 2024

faster pussycat
premature optimization
python
UI
Figure 1

marimo is a Python-specific alternative note which solves many pain points of Jupyter (HT Jean-Michel Perraud).

The FAQ explains it best. tl;dr: Marimo is a differently imperfect compromise between the needs of reproducibility and reliability. The leakiness of its abstractions is likely to spill less on my trousers than jupyter, while being more interactive than a pure Python script.

marimo solves problems in reproducibility, maintainability, interactivity, reusability, and shareability of notebooks.

Reproducibility. In Jupyter notebooks, the code you see doesn’t necessarily match the outputs on the page or the program state. If you delete a cell, its variables stay in memory, which other cells may still reference; users can execute cells in arbitrary order. This leads to widespread reproducibility issues. One study analysed 10 million Jupyter notebooks and found that 36% of them weren’t reproducible.

In contrast, marimo guarantees that your code, outputs, and program state are consistent, eliminating hidden state and making your notebook reproducible. marimo achieves this by intelligently analysing your code and understanding the relationships between cells, and automatically re-running cells as needed.

Maintainability. marimo notebooks are stored as pure Python programs (.py files). This lets you version them with git; in contrast, Jupyter notebooks are stored as JSON and require extra steps to version.

Interactivity. marimo notebooks come with UI elements that are automatically synchronised with Python (like sliders, dropdowns); eg, scrub a slider and all cells that reference it are automatically re-run with the new value. This is difficult to get working in Jupyter notebooks.

Reusability. marimo notebooks can be executed as Python scripts from the command-line (since they’re stored as .py files). In contrast, this requires extra steps to do for Jupyter, such as copying and pasting the code out or using external frameworks. In the future, we’ll also let you import symbols (functions, classes) defined in a marimo notebook into other Python programs/notebooks, something you can’t easily do with Jupyter.

Shareability. Every marimo notebook can double as an interactive web app, complete with UI elements, which you can serve using the marimo run command. This isn’t possible in Jupyter without substantial extra effort.

1 Installation

pip install marimo

or see Getting Started - marimo.

2 IDE integration

IDE integration is marimo’s weak suit for me thus far. I use VS Code for Python and the marimo extension is a little janky thus far.

As per this GitHub issue I needed the following config for VS Code to find the marimo interpreter to stop it beachballing forever:

{
  "python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python",
  "marimo.marimoPath": "${workspaceFolder}/.venv/bin/marimo",
  "marimo.debug": true
}

If you have your local Python environment somewhere else, you would need to change that too.

It seems to be incompatible with ruff auto-linting.

3 Markdown

There is rich markdown support. Nice.

I could not see it documented, but for markdown to work, the first cell in the notebook should say

import marimo as mo

Symptoms of not doing this: the error NameError('name 'mo' is not defined').

4 File format

The file format of marimo is clever. It uses Python code to encode Python code. That might not sound revolutionary, but Jupyter used JSON to encode Python code and that has created an ongoing quagmire.

In marimo, there are Jupyter-like cells, but they get their functionality via decorators. They also execute like normal Python code when needed. Here is an example for the curious as to what a marimo notebook looks like on the inside:

import marimo

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


@app.cell
def __():
    import marimo as mo
    return (mo,)


@app.cell
def __():
    print("Hello world")
    return


@app.cell
def __(mo):
    mo.md(
        r"""
        ## Markdown is supported

        You can write in **bold**.
        """
    )
    return


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

5 Remote access

Marimo runs a web app which can be accessed remotely. One can forward connections manually, Pro-tip: it will automatically set up a tunnel if you run it using a VS Code Remote connection.

6 Debugging

For some reason it’s only documented in an image on linkedin, but interactive debuggers are supported.

pdb.set_trace()
breakpoint()

7 Tips

dotenv is weird in marimo:

dotenv.load_dotenv(dotenv.find_dotenv(usecwd=True))

There is native cache support.

It can run (purely) in the browser without installing python.

Extra UI widgets? koaning/wigglystuff: A collection of creative AnyWidgets for Python notebook environments.

Prototype Quarto integration: marimo-quarto.

Execution order is worth reading about: marimo ensures that cells are executed in a consistent order to maintain reproducibility. This means that if you modify a cell, marimo will automatically re-run any dependent cells to ensure that the notebook’s state is consistent. That means that cells are not executed in the order you see them on the page, so e.g. you can put boilerplate imports at the end of the notebook. I would not do that, because why introduce weirdness?