marimo apps are stored as pure Python files.
These files are:
- easily versioned with git, producing small diffs
- legible for both humans and machines
- formattable using your tool of choice
- usable as Python scripts, with UI elements taking their default values
mo.md(intro)
Click the app window icon in the bottom-left to hide this app's code,
or use the "fold code" shortcut to fold all code cells.
mo.accordion(%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%22Tip%3A%20hide%20this%20tutorial's%20code%22%3A%20(%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20%20%20%20%20Click%20the%20app%20window%20icon%20in%20the%20bottom-left%20to%20hide%20this%20app's%20code%2C%0A%20%20%20%20%20%20%20%20or%20use%20the%20%22fold%20code%22%20shortcut%20to%20fold%20all%20code%20cells.%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%7D%0A)
Example
Consider a marimo notebook with the following three cells.
First cell:
Second cell:
text = mo.ui.text(value="Hello, World!")
text
Third cell:
mo.md(example_program)
For the above example, marimo would generate the following file
contents:
import marimo
__generated_with = "0.6.11"
app = marimo.App()
@app.cell
def __(text):
print(text.value)
return
@app.cell
def __(mo):
text = mo.ui.text(value="Hello, World!")
text
return text,
@app.cell
def __():
import marimo as mo
return mo,
if __name__ == "__main__":
app.run()
As you can see, this is pure Python. This is part of the reason why
marimo's generated files are git-friendly: small changes made using
the marimo editor result in small changes to the file that marimo
generates.
mo.md(file_contents)
Properties
marimo’s file format was designed to be easy to read and easy to work with, while also serving the needs of the marimo library. You can even edit the generated file’s cells directly, using your favorite text editor, and format the file with your favorite code formatter.
We explain some properties of marimo’s file format below.
In the dataflow
tutorial, we saw that cells are like functions mapping
their refs (the global variables they uses but don't define) to their
defs (the global variables they define). The generated code makes this
analogy explicit.
In the generated code, there is a function for each cell. The arguments
of the function are the cell's refs , and its returned variables are
its defs.
For example, the code
@app.cell
def __(mo):
text = mo.ui.text(value="Hello, World!")
text
return text,
says that the cell takes as input a variable called mo
, and it creates
a global variable called text
.
In contrast, the code
@app.cell
def __():
import marimo as mo
return mo,
says that the cell doesn't depend on any other cells (its argument list
is empty), though it does create the variable mo
which the previous
cell requires as input. Cells are stored in the order that they are arranged in the marimo
editor. So if you want to rearrange
your cells using your favorite text editor, just rearrange the
order that they're defined in the file.
marimo guarantees that however your source code was
formatted in the marimo editor is exactly how it will be stored in
the generated code. For example, whitespace, line breaks, and so on are
all preserved exactly. This means that you can touch up formatting in
your text editor, either manually or using automated formatters like
Black, and be confident that your changes will be preserved.
If you want to, you can replace the default names for cell functions
with meaningful ones.
For example, change
@app.cell
def __(text):
print(text.value)
return
to
@app.cell
def echo(text):
print(text.value)
return
This can make the generated code more readable. marimo's generated code is pure Python; no magical syntax.
If when editing a cell, you forget to include all a cell's refs in its
argument list, or all its defs in its returns, marimo will raise a
helpful error message the next time you try to open it in the marimo
editor. So don't worry that you'll botch a cell's signature when editing
it.
At the top of the generated code, a variable named app
is created.
This object collects the cells into a dataflow graph, using the cell
decorator.
You can run marimo apps as scripts at the command line,
using Python. This will execute the cells in a
topologically sorted order, just as they would run if you opened the app
with marimo edit
.
For example: running our example as a script would print Hello
World!
to the console.
mo.accordion(properties)
intro%20%3D%20%22%22%22%0A%23%20File%20Format%0A%0Amarimo%20apps%20are%20stored%20as%20pure%20Python%20files.%0A%0AThese%20files%20are%3A%0A%0A-%20easily%20versioned%20with%20git%2C%20producing%20small%20diffs%0A-%20legible%20for%20both%20humans%20and%20machines%0A-%20formattable%20using%20your%20tool%20of%20choice%0A-%20usable%20as%20Python%20%20scripts%2C%20with%20UI%20%20elements%20taking%20their%20default%20values%0A%22%22%22
file_contents%20%3D%20f%22%22%22%0A%20%20%20%20For%20the%20above%20example%2C%20marimo%20would%20generate%20the%20following%20file%20%0A%20%20%20%20contents%3A%0A%0A%20%20%20%20%60%60%60python3%0A%20%20%20%20import%20marimo%0A%0A%20%20%20%20__generated_with%20%3D%20%22%7Bmo.__version__%7D%22%0A%20%20%20%20app%20%3D%20marimo.App()%0A%0A%20%20%20%20%40app.cell%0A%20%20%20%20def%20__(text)%3A%0A%20%20%20%20%20%20%20%20print(text.value)%0A%20%20%20%20%20%20%20%20return%0A%0A%20%20%20%20%40app.cell%0A%20%20%20%20def%20__(mo)%3A%0A%20%20%20%20%20%20%20%20text%20%3D%20mo.ui.text(value%3D%22Hello%2C%20World!%22)%0A%20%20%20%20%20%20%20%20text%0A%20%20%20%20%20%20%20%20return%20text%2C%0A%0A%20%20%20%20%40app.cell%0A%20%20%20%20def%20__()%3A%0A%20%20%20%20%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20%20%20%20%20return%20mo%2C%0A%0A%20%20%20%20if%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20%20%20%20%20app.run()%0A%20%20%20%20%60%60%60%0A%0A%20%20%20%20As%20you%20can%20see%2C%20this%20is%20_pure%20Python_.%20This%20is%20part%20of%20the%20reason%20why%0A%20%20%20%20marimo's%20generated%20files%20are%20**git-friendly**%3A%20small%20changes%20made%20using%20%0A%20%20%20%20the%20marimo%20editor%20result%20in%20small%20changes%20to%20the%20file%20that%20marimo%20%0A%20%20%20%20generates.%0A%22%22%22
example_program%20%3D%20%22%22%22%0A%23%23%20Example%0A%0AConsider%20a%20marimo%20notebook%20with%20the%20following%20three%20cells.%0A%0AFirst%20cell%3A%0A%60%60%60python3%0Aprint(text.value)%0A%60%60%60%0A%0ASecond%20cell%3A%0A%60%60%60python3%0Atext%20%3D%20mo.ui.text(value%3D%22Hello%2C%20World!%22)%0Atext%0A%60%60%60%0A%0AThird%20cell%3A%0A%60%60%60python3%0Aimport%20marimo%20as%20mo%0A%60%60%60%0A%22%22%22
properties%20%3D%20%7B%0A%20%20%20%20%22Cells%20are%20functions%22%3A%20%22%22%22%0A%20%20%20%20In%20the%20%60dataflow%60%20tutorial%2C%20we%20saw%20that%20cells%20are%20like%20functions%20mapping%20%0A%20%20%20%20their%20refs%20(the%20global%20%20variables%20they%20uses%20but%20don't%20define)%20to%20their%20%0A%20%20%20%20defs%20(the%20global%20variables%20they%20define).%20The%20generated%20code%20makes%20this%20%0A%20%20%20%20analogy%20explicit.%0A%0A%20%20%20%20In%20the%20generated%20code%2C%20there%20is%20a%20function%20for%20each%20cell.%20The%20arguments%20%0A%20%20%20%20of%20%20the%20function%20are%20the%20cell's%20refs%20%2C%20and%20its%20returned%20variables%20are%20%0A%20%20%20%20its%20defs.%0A%0A%20%20%20%20For%20example%2C%20the%20code%0A%0A%20%20%20%20%60%60%60python3%0A%20%20%20%20%40app.cell%0A%20%20%20%20def%20__(mo)%3A%0A%20%20%20%20%20%20%20%20text%20%3D%20mo.ui.text(value%3D%22Hello%2C%20World!%22)%0A%20%20%20%20%20%20%20%20text%0A%20%20%20%20%20%20%20%20return%20text%2C%0A%20%20%20%20%60%60%60%0A%0A%20%20%20%20says%20that%20the%20cell%20takes%20as%20input%20a%20variable%20called%20%60mo%60%2C%20and%20it%20creates%0A%20%20%20%20a%20global%20variable%20called%20%60text%60.%0A%0A%20%20%20%20In%20contrast%2C%20the%20code%0A%0A%20%20%20%20%60%60%60python3%0A%20%20%20%20%40app.cell%0A%20%20%20%20def%20__()%3A%0A%20%20%20%20%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20%20%20%20%20return%20mo%2C%0A%20%20%20%20%60%60%60%0A%0A%20%20%20%20says%20that%20the%20cell%20doesn't%20depend%20on%20any%20other%20cells%20(its%20argument%20list%20%0A%20%20%20%20is%20%20empty)%2C%20though%20it%20does%20create%20the%20variable%20%60mo%60%20which%20the%20previous%20%0A%20%20%20%20cell%20requires%20as%20input.%0A%20%20%20%20%22%22%22%2C%0A%20%20%20%20%22Cells%20are%20stored%20in%20presentation%20order%22%3A%20%22%22%22%0A%20%20%20%20Cells%20are%20stored%20in%20the%20order%20that%20they%20are%20arranged%20in%20the%20marimo%20%0A%20%20%20%20editor.%20So%20if%20you%20want%20to%20rearrange%0A%20%20%20%20your%20cells%20using%20your%20favorite%20text%20editor%2C%20just%20rearrange%20the%0A%20%20%20%20order%20that%20they're%20defined%20in%20the%20file.%0A%20%20%20%20%22%22%22%2C%0A%20%20%20%20%22Text%20formatting%20is%20preserved%22%3A%20%22%22%22%0A%20%20%20%20marimo%20guarantees%20that%20however%20your%20source%20code%20was%0A%20%20%20%20formatted%20in%20the%20marimo%20editor%20is%20exactly%20how%20it%20will%20be%20stored%20in%0A%20%20%20%20the%20generated%20code.%20For%20example%2C%20whitespace%2C%20line%20breaks%2C%20and%20so%20on%20are%0A%20%20%20%20all%20preserved%20exactly.%20This%20means%20that%20you%20can%20touch%20up%20formatting%20in%0A%20%20%20%20your%20text%20editor%2C%20either%20manually%20or%20using%20automated%20formatters%20like%20%0A%20%20%20%20Black%2C%20and%20be%20confident%20that%20your%20changes%20will%20be%20preserved.%0A%20%20%20%20%22%22%22%2C%0A%20%20%20%20%22Cell%20functions%20can%20have%20names%22%3A%20%22%22%22%0A%20%20%20%20If%20you%20want%20to%2C%20you%20can%20replace%20the%20default%20names%20for%20cell%20functions%20%0A%20%20%20%20with%20meaningful%20ones.%0A%0A%20%20%20%20For%20example%2C%20change%0A%0A%20%20%20%20%60%60%60python3%0A%20%20%20%20%40app.cell%0A%20%20%20%20def%20__(text)%3A%0A%20%20%20%20%20%20%20%20print(text.value)%0A%20%20%20%20%20%20%20%20return%0A%20%20%20%20%60%60%60%0A%0A%20%20%20%20to%20%0A%0A%20%20%20%20%60%60%60python3%0A%20%20%20%20%40app.cell%0A%20%20%20%20def%20echo(text)%3A%0A%20%20%20%20%20%20%20%20print(text.value)%0A%20%20%20%20%20%20%20%20return%0A%20%20%20%20%60%60%60%0A%0A%20%20%20%20This%20can%20make%20the%20generated%20code%20more%20readable.%0A%20%20%20%20%22%22%22%2C%0A%20%20%20%20%22No%20magical%20tokens%22%3A%20%22%22%22%0A%20%20%20%20marimo's%20generated%20code%20is%20pure%20Python%3B%20no%20magical%20syntax.%0A%20%20%20%20%22%22%22%2C%0A%20%20%20%20%22Helpful%20error%20messages%22%3A%20%22%22%22%0A%20%20%20%20If%20when%20editing%20a%20cell%2C%20you%20forget%20to%20include%20all%20a%20cell's%20refs%20in%20its%0A%20%20%20%20argument%20list%2C%20or%20all%20its%20defs%20in%20its%20returns%2C%20marimo%20will%20raise%20a%20%0A%20%20%20%20helpful%20error%20message%20the%20next%20time%20you%20try%20to%20open%20it%20in%20the%20marimo%20%0A%20%20%20%20editor.%20So%20don't%20worry%20that%20you'll%20botch%20a%20cell's%20signature%20when%20editing%20%0A%20%20%20%20it.%0A%20%20%20%20%22%22%22%2C%0A%20%20%20%20%22The%20%60app%60%20object%22%3A%20%22%22%22%0A%20%20%20%20At%20the%20top%20of%20the%20generated%20code%2C%20a%20variable%20named%20%60app%60%20is%20created.%20%0A%20%20%20%20This%20object%20collects%20the%20cells%20into%20a%20dataflow%20graph%2C%20using%20the%20%60cell%60%20%0A%20%20%20%20decorator.%20%0A%20%20%20%20%22%22%22%2C%0A%20%20%20%20%22Runnable%20as%20a%20script%22%3A%20%22%22%22%0A%20%20%20%20You%20can%20run%20marimo%20apps%20as%20scripts%20at%20the%20command%20line%2C%0A%20%20%20%20using%20Python.%20This%20will%20execute%20the%20cells%20in%20a%0A%20%20%20%20topologically%20sorted%20order%2C%20just%20as%20they%20would%20run%20if%20you%20opened%20the%20app%20%0A%20%20%20%20with%20%60marimo%20edit%60.%0A%0A%20%20%20%20For%20example%3A%20running%20our%20example%20as%20a%20script%20would%20print%20%60Hello%20%0A%20%20%20%20World!%60%20to%20the%20console.%0A%20%20%20%20%22%22%22%2C%0A%7D
import%20marimo%20as%20mo
Back to top