Skip To Article

Execute Notebooks at Build Time

Generate figures and other rich content using Jupyter kernels

The MyST CLI can execute your notebooks and markdown files by passing the --execute flag to the start and build commands, i.e.:

myst start --execute
myst build --execute

The following computational content will be executed:

  • Notebook cells will be executed in the order they appeared in a notebook (ie, a file ending in .ipynb).
  • {code-block} directives will be executed similar to a code block cell. See Executable Markdown Files for more information.
  • Inline expressions with the {eval} role can be used to insert the outputs of a computation in-line with other text.

Expect a code-cell to fail

By default, MyST will stop executing a notebook if a cell raises an error. If instead you’d like MyST to continue executing subsequent cells (e.g., in order to demonstrate an expected error message), add the raises-exception tag to the cell. If a cell with this tag raises an error, then the error is provided with the cell output, and MyST will continue executing the rest of the cells in a notebook.

The easiest way to add cell tags is via the JupyterLab interface. Additionally, you can specify tags (and other cell metadata) with markdown using the {code-cell} directive.

Here’s an example of adding this tag with a {code-cell} directive:

```{code-cell}
:tags: raises-exception

print("Hello" + 10001)
```

Skip particular code-cells

Sometimes, you might have a notebook containing code that you don’t want to execute. For example, you might have code-cells that prompt the user for input, which should be skipped during a website build. MyST understands the same skip-execution cell-tag that other Jupyter Notebook tools (such as Jupyter Book) use to prevent a cell from being executed.

For Markdown notebooks using the {code-cell} directive, the skip-execution tag can be added as follows:

```{code-cell}
:tags: skip-execution

name = input("What is your name?")
```

Cache execution outputs

When MyST executes your notebook, it will store the outputs in a cache in a folder called execute/ in your MyST build folder. On subsequent builds, MyST will re-use this cache rather than re-execute.

If you change the computational content of a notebook or a markdown page (ie, code in a code cell, or in an inline expression), then this cache will be reset and the code will be re-executed at the next build.

Force execution by deleting the cache

If you’d like to force re-execution of all the code in your MyST documents, use the following command:

myst clean --execute

Alternatively, you can manually delete the execute/ folder in your build folder, e.g.:

rm -rf _build/execute

How MyST executes your code

MyST uses a Jupyter Server to execute your code. Jupyter Server is distributed as a Python package, which can be installed from PyPI or conda-forge, e.g.

pip install jupyter-server

Jupyter Server is only responsible for orchestrating execution of your code. To actually perform execution, you must also install a kernel. For Python, this might be ipykernel, e.g.

pip install ipykernel

If Jupyter Server is installed and the --execute flag is passed to myst start or myst build, then MyST will attempt to find a healthy existing Jupyter Server. Internally, this is performed using python -m jupyter_server list. If no existing servers are found, then MyST will attempt to launch one using python -m jupyter_server.

Manually launch a Jupyter server

You can manually launch a Jupyter server and instruct MyST to use it for computation (rather than having MyST start its own Jupyter server). This gives you more control over the process that executes your content, including specifying Jupyter servers that exist on non-local hardware (e.g. running in the cloud).

To manually specify a server, you must set two variables:

  • JUPYTER_BASE_URL: a URL where the server can be found. On a local machine, this is by default http://localhost:8888.
  • JUPYTER_TOKEN: the token that allows access to the Jupyter server.

For example, the following code sets these variables, then starts a Jupyter server with them so that MyST will use them to execute code:

# Set the port for our local Jupyter process
port="8888"

# Define environment variables that will be used by MyST
# We'll use the values of these variables in our Jupyter server as well.
export JUPYTER_BASE_URL="http://localhost:${port}"
export JUPYTER_TOKEN="my-jupyter-token"

# Start the Jupyter server re-using the variables above
jupyter server --IdentityProvider.token="${JUPYTER_TOKEN}" --ServerApp.port="${port}" &

# Run the MyST build
# It will use the JUPYTER_* variables above to look for the server.
myst build --execute

# Stop the Jupyter server!
kill %1
MyST MarkdownMyST Markdown
Community-driven tools for the future of technical communication and publication, part of Jupyter.