Script Rendering for Jupyter
This feature is new in the upcoming Quarto 1.4 release. To use the feature now, you’ll need to download and install the Quarto pre-release.
Overview
Quarto v1.4 includes support for rendering script files (e.g. .py
, .jl
, or .r
) that are specially formatted as notebooks. Script rendering makes use of the percent format that is supported by several other other tools including Spyder, VS Code, PyCharm, and Jupytext.
For example, here is a Python script that includes both markdown and code cells:
script.py
# %% [markdown]
# ---
# title: Palmer Penguins
# author: Norah Jones
# date: 3/12/23
# ---
# %%
#| echo: false
import pandas as pd
= pd.read_csv("palmer-penguins.csv")
df
# %% [markdown]
"""
## Exploring the data
See @fig-bill-sizes for an exploration of bill sizes by species.
"""
# %%
#| label: fig-bill-sizes
#| fig-cap: Bill Sizes by Species
import matplotlib.pyplot as plt
import seaborn as sns
= sns.FacetGrid(df, hue="species", height=3, aspect=3.5/1.5)
g map(plt.scatter, "bill_length_mm", "bill_depth_mm").add_legend() g.
Code cells are delimited by # %%
and markdown cells are delimited by # %% [markdown]
. Markdown content can either be included in single line comments (#
) or multi-line strings ("""
), both of which are illustrated above.
Note that cell options are included as normal using #|
prefixed comments (e.g. #| echo: false
). Also note that you can include blank lines within cells (cells continue until another cell is encountered).
Render and Preview
Rendering and previewing notebook scripts works exactly like .qmd
and .ipynb
files. For example, the following commands are all valid:
$ quarto render script.py
$ quarto render script.jl
$ quarto preview script.py
$ quarto preview script.jl
Jupyter scripts rendered with Quarto must begin with a # %% [markdown]
cell (which normally includes the title
and other YAML options). This convention is how Quarto knows that it should parse code cells using the percent format (as opposed to other notebook as script formats that may be supported in the future).
Jupyter script rendering is supported for Python, Julia, and R. Note that for R scripts, the IRkernel will be used to execute code cells rather than Knitr (support for the Knitr spin script format is planned but not yet implemented).
The latest version (v1.97.0) of the Quarto VS Code Extension also implements support for render and preview of Jupyter scripts.
Generating Markdown
Jupyter scripts are especially convenient when most of your document consists of code that dynamically generates markdown. You can write markdown from Python using functions in the IPython.display
module. For example:
#| %%
#| echo: false
= 10
radius from IPython.display import display, Markdown
"The _radius_ of the circle is **{radius}**."
display(Markdown(format(radius = radius))) .
Note that dynamically generated markdown will still be enclosed in the standard Quarto output divs. If you want to remove all of Quarto’s default output enclosures use the output: asis
option. For example:
#| %%
#| echo: false
#| output: asis
= 10
radius from IPython.display import display, Markdown
"The _radius_ of the circle is **{radius}**."
display(Markdown(format(radius = radius))) .
Raw Cells
You can include raw cells (e.g. HTML or LaTeX) within scripts using the # %% [raw]
cell delimiter along with a format
attribute, for example:
# %% [raw] format="html"
"""
<iframe width="560" height="315" src="https://www.youtube.com/embed/lJIrF4YjHfQ?si=aP7PxA1Pz8IIoQUX"></iframe>
"""
Scripts in Projects
Jupyter scripts can also be included within projects (e.g. websites, blogs, etc.). Scripts within projects are only rendered by Quarto when they have a markdown cell at the top (e.g. # %% [markdown]
).
If for some reason you need to ignore a script that begins with a markdown cell, you can create an explict render list in _quarto.yml
that excludes individual scripts as required, for example:
project:
type: website
render:
- "*.{qmd,ipynb,py}"
- "!utils.py"
Note that this technique is documented for the sake of completeness—in practice you should almost never need to do this since Python scripts rarely begin with # %% [markdown]
unless you are authoring them specifically as notebooks.