Jupyter Notebook Tools for Sphinx#
nbsphinx
is a Sphinx extension that provides a source parser for
*.ipynb
files.
Custom Sphinx directives are used to show Jupyter Notebook code cells (and of
course their results) in both HTML and LaTeX output.
Un-evaluated notebooks – i.e. notebooks without stored output cells – will be
automatically executed during the Sphinx build process.
- Quick Start:
Install
nbsphinx
Edit your
conf.py
and add'nbsphinx'
toextensions
.Edit your
index.rst
and add the names of your*.ipynb
files to thetoctree
.Run Sphinx!
- Online documentation (and example of use):
- Source code repository (and issue tracker):
- License:
MIT – see the file
LICENSE
for details.
All of the following content was generated from Jupyter notebooks, except for the sections Normal reStructuredText Files, Contributing, References and Version History, which were generated from Sphinx’s built-in reStructuredText format. The sections Custom Notebook Formats, Dummy Notebook 2 for Gallery and Using Markdown Files are using alternative storage formats for Jupyter notebooks, see Custom Notebook Formats for details.
click here to see full table of contents
Installation#
Note that some packages may be out of date. You can always get the newest nbsphinx
release from PyPI (using pip
). If you want to try the latest development version, have a look at the section Contributing.
nbsphinx
Packages#
If you are using the conda
package manager (e.g. with Miniforge or Miniconda), you can install nbsphinx
from the conda-forge channel:
conda install -c conda-forge nbsphinx
You can of course also install nbsphinx
with pip
, Python’s own package manager:
python3 -m pip install nbsphinx
Depending on your Python installation, you may have to use python
instead of python3
. If you have installed the module already, you can use the --upgrade
flag to get the newest release.
There are more packages available. For an overview, see repology.
nbsphinx
Prerequisites#
Some of the aforementioned packages will install some of these prerequisites automatically, some of the things may be already installed on your computer anyway.
Python#
Of course you’ll need Python, because both Sphinx and nbsphinx
are implemented in Python. There are many ways to get Python. If you don’t know which one is best for you, you can try Miniforge.
Sphinx#
You’ll need Sphinx as well, because nbsphinx
is just a Sphinx extension and doesn’t do anything on its own.
If you use conda
, you can get Sphinx from the conda-forge channel:
conda install -c conda-forge sphinx
Alternatively, you can install it with pip
(see below):
python3 -m pip install Sphinx
pip#
Recent versions of Python already come with pip
pre-installed. If you don’t have it, you can install it manually.
pandoc#
The stand-alone program pandoc is used to convert Markdown content to something Sphinx can understand. You have to install this program separately, ideally with your package manager. If you are using conda
, you can install pandoc from the conda-forge channel:
conda install -c conda-forge pandoc
If that doesn’t work out for you, have a look at pandoc
’s installation instructions.
Note
The use of pandoc
in nbsphinx
is temporary, but will likely stay that way for a long time, see issue #36.
Pygments Lexer for Syntax Highlighting#
To get proper syntax highlighting in code cells, you’ll need an appropriate Pygments lexer. This of course depends on the programming language of your Jupyter notebooks (more specifically, the pygments_lexer
metadata of your notebooks).
For example, if you use Python in your notebooks, you’ll have to have the IPython
package installed, e.g. with
conda install -c conda-forge ipython
or
python3 -m pip install IPython
Note
If you are using Anaconda with the default channel and syntax highlighting in code cells doesn’t seem to work, you can try to install IPython from the conda-forge
channel or directly with pip
, or as a work-around, add 'IPython.sphinxext.ipython_console_highlighting'
to extensions
in your conf.py
.
For details, see Anaconda issue #1430 and nbsphinx issue #24.
Jupyter Kernel#
If you want to execute your notebooks during the Sphinx build process (see Controlling Notebook Execution), you need an appropriate Jupyter kernel installed.
For example, if you use Python, you should install the ipykernel
package, e.g. with
conda install -c conda-forge ipykernel
or
python3 -m pip install ipykernel
If you created your notebooks yourself with Jupyter, it’s very likely that you have the right kernel installed already.
Note
If your automatic builds on https://readthedocs.org are failing due to an error like the one below, add ipykernel
to docs/requirements.txt
or doc/environment.yml
to resolve.
jupyter_client.kernelspec.nosuchkernel: no such kernel named python3
Usage#
Project Setup#
In the directory with your notebook files, run this command (assuming you have Sphinx and nbsphinx
installed already):
python3 -m sphinx.cmd.quickstart
Answer the questions that appear on the screen. In case of doubt, just press the <Return>
key repeatedly to take the default values.
After that, there will be a few brand-new files in the current directory. You’ll have to make a few changes to the file named conf.py
. You should make sure that the extensions
setting at least contains 'nbsphinx'
(but you might want to add other useful extensions as well):
extensions = [
'nbsphinx',
]
For an example, see this project’s conf.py file.
Once your conf.py
is in place, edit the file named index.rst
and add the file names of your notebooks (without the .ipynb
extension) to the toctree directive. For an example, see this project’s doc/index.rst
file.
Alternatively, you can delete the file index.rst
and replace it with your own notebook called index.ipynb
which will serve as main page. In this case you can create the main toctree in index.ipynb
.
Running Sphinx#
To create the HTML pages, use this command:
python3 -m sphinx <source-dir> <build-dir>
If you have many notebooks, you can do a parallel build by using the -j
option:
python3 -m sphinx <source-dir> <build-dir> -j<number-of-processes>
For example, if your source files are in the current directory and you have 4 CPU cores, you can run this:
python3 -m sphinx . _build -j4
Afterwards, you can find the main HTML file in _build/index.html
.
Subsequent builds will be faster, because only those source files which have changed will be re-built. To force re-building all source files, use the -E
option.
Note
By default, notebooks will be executed during the Sphinx build process only if they do not have any output cells stored. See Controlling Notebook Execution.
To create LaTeX output, use:
python3 -m sphinx <source-dir> <build-dir> -b latex
If you don’t know how to create a PDF file from the LaTeX output, you should have a look at Latexmk (see also this tutorial).
Sphinx can automatically check if the links you are using are still valid. Just invoke it like this:
python3 -m sphinx <source-dir> <build-dir> -b linkcheck
Watching for Changes with sphinx-autobuild
#
If you think it’s tedious to run the Sphinx build command again and again while you make changes to your notebooks, you’ll be happy to hear that there is a way to avoid that: sphinx-autobuild!
It can be installed with
python3 -m pip install sphinx-autobuild
You can start auto-building your files with
python3 -m sphinx_autobuild <source-dir> <build-dir>
This will start a local webserver which will serve the generated HTML pages at http://localhost:8000/. Whenever you save changes in one of your notebooks, the appropriate HTML page(s) will be re-built and when finished, your browser view will be refreshed automagically. Neat!
You can also abuse this to auto-build the LaTeX output:
python3 -m sphinx_autobuild <source-dir> <build-dir> -b latex
However, to auto-build the final PDF file as well, you’ll need an additional tool. Again, you can use latexmk
for this (see above). Change to the build directory and run
latexmk -pdf -pvc
If your PDF viewer isn’t opened because of LaTeX build errors, you can use the command line flag -f
to force creating a PDF file.
Automatic Creation of HTML and PDF output on readthedocs.org#
There are two different methods, both of which are described below.
In both cases, you’ll first have to create an account on https://readthedocs.org/ and connect your GitLab/Github/Bitbucket/… account. Instead of connecting, you can also manually add any publicly available Git/Subversion/Mercurial/Bazaar/… repository.
After doing the steps described below, you only have to “push” to your repository, and the HTML pages and the PDF file of your stuff are automagically created on readthedocs.org. Awesome!
You can even have different versions of your stuff, just use Git tags and branches and select in the readthedocs.org settings which of those should be created.
Note
If you want to execute notebooks (see Controlling Notebook Execution), you’ll need to install the appropriate Jupyter kernel. In the examples below, the IPython kernel is installed from the packet ipykernel
.
Using requirements.txt
#
Create a file named
.readthedocs.yml
in the main directory of your repository with the following contents:version: 2 build: os: ubuntu-22.04 tools: python: "3" python: install: - requirements: doc/requirements.txt
For further options see https://docs.readthedocs.io/en/latest/config-file/.
Create a file named
doc/requirements.txt
(or whatever you chose in the previous step) containing the requiredpip
packages:ipykernel nbsphinx
You can also install directly from Github et al., using a specific branch/tag/commit, e.g.
git+https://github.com/spatialaudio/nbsphinx.git@master
Using conda
#
Create a file named
.readthedocs.yml
in the main directory of your repository with the following contents:version: 2 formats: all conda: environment: doc/environment.yml
For further options see https://docs.readthedocs.io/en/latest/config-file/.
Create a file named
doc/environment.yml
(or whatever you chose in the previous step) describing a conda environment like this:channels: - conda-forge dependencies: - python>=3 - pandoc - ipykernel - pip - pip: - nbsphinx
It is up to you if you want to install
nbsphinx
withconda
or withpip
(but note that theconda
package might be outdated). And you can of course add furtherconda
andpip
packages. You can also install packages directly from Github et al., using a specific branch/tag/commit, e.g.- pip: - git+https://github.com/spatialaudio/nbsphinx.git@master
Note
The specification of the conda-forge
channel is recommended because it tends to have more recent package versions than the default channel.
Automatic Creation of HTML and PDF output on GitLab Pages#
When using GitLab pages, you can use nbsphinx by adding the file .gitlab-ci.yml
to your repo and copying the following lines into this file:
image: python:3-slim
variables:
PIP: python3 -m pip
SPHINX: python3 -m sphinx -W --keep-going --color
build-docs:
stage: build
script:
- apt-get update -y
- apt-get install -y --no-install-recommends pandoc
- $PIP install -r doc/requirements.txt
- $SPHINX -d doctrees doc html -b html
- $SPHINX -d doctrees doc linkcheck -b linkcheck
artifacts:
when: always
paths:
- html
- linkcheck/output.*
pages:
stage: deploy
variables:
GIT_STRATEGY: none
script:
- mv html public
artifacts:
paths:
- public
rules:
- if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
HTML Themes#
The nbsphinx
extension does not provide its own theme, you can use any of the available themes or create a custom one, if you feel like it.
The following (incomplete) list of themes contains up to three links for each theme:
The documentation (or the official sample page) of this theme (if available; see also the documentation of the built-in Sphinx themes)
How the
nbsphinx
documentation looks when using this themeHow to enable this theme using either
requirements.txt
orreadthedocs.yml
and theme-specific settings (in some cases)
Sphinx’s Built-In Themes#
3rd-Party Themes#
If you know of another Sphinx theme that should be included here, please open an issue on Github. An overview of many more themes can be found at https://sphinx-themes.org/.
Using Notebooks with Git#
Git is extremely useful for managing source code and it can and should also be used for managing Jupyter notebooks. There is one caveat, however: Notebooks can contain output cells with rich media like images, plots, sounds, HTML, JavaScript and many other types of bulky machine-created content. This can make it hard to work with Git efficiently, because changes in those bulky contents can completely obscure the more interesting human-made changes in text and source code. Working with multiple collaborators on a notebook can become very tedious because of this.
It is therefore highly recommended that you remove all outputs from your notebooks before committing changes to a Git repository (except for the reasons mentioned in Pre-Executing Notebooks).
If there are no output cells in a notebook, nbsphinx
will by default execute the notebook, and the pages generated by Sphinx will therefore contain all the output cells. See Controlling Notebook Execution for how this behavior can be customized.
In the Jupyter Notebook application, you can manually clear all outputs by selecting “Cell” \(\to\) “All Output” \(\to\) “Clear” from the menu. In JupyterLab, the menu items are “Edit” \(\to\) “Clear All Outputs”.
There are several tools available to remove outputs from multiple files at once without having to open them separately. You can even include such a tool as “clean/smudge filters” into your Git workflow, which will strip the output cells automatically whenever a Git command is executed. For details, have a look at those links:
https://tillahoffmann.github.io/2017/04/17/versioning-jupyter-notebooks-with-git.html
http://timstaley.co.uk/posts/making-git-and-jupyter-notebooks-play-nice/
https://jamesfolberth.org/articles/2017/08/07/git-commit-hook-for-jupyter-notebooks/
https://github.com/ResearchSoftwareActions/EnsureCleanNotebooksAction
Configuration#
The following configuration values can be used in the conf.py
file, see Project Setup.
Sphinx Configuration Values#
All configuration values are described in the Sphinx documentation, here we mention only the ones which may be relevant in combination with nbsphinx
.
exclude_patterns
#
Sphinx builds all potential source files (reST files, Jupyter notebooks, …) that are in the source directory (including any sub-directories), whether you want to use them or not. If you want certain source files not to be built, specify them in exclude_patterns. For example, you might want to ignore source files in your build directory:
exclude_patterns = ['_build']
Note that the directory .ipynb_checkpoints
is automatically added to exclude_patterns
by nbsphinx
.
extensions
#
This is the only required value. You have to add 'nbsphinx'
to the list of extensions, otherwise it won’t work.
Other interesting extensions are:
'sphinx.ext.mathjax'
(Sphinx loads this by default) for math formulas'sphinxcontrib.bibtex'
for bibliographic references'sphinxcontrib.rsvgconverter'
for SVG->PDF conversion in LaTeX output'sphinx_copybutton'
for adding “copy to clipboard” buttons to all text/code boxes
html_css_files
#
See Custom CSS and html_css_files.
html_sourcelink_suffix
#
By default, a .txt
suffix is added to source files. This is only relevant if the chosen HTML theme supports source links and if html_show_sourcelink is True
.
Jupyter notebooks with the suffix .ipynb.txt
are normally not very useful, so if you want to avoid the additional suffix, set html_sourcelink_suffix to the empty string:
html_sourcelink_suffix = ''
latex_additional_files
#
latex_additional_files can be useful if you are using BibTeX files, see References.
mathjax3_config
#
The configuration value mathjax3_config can be useful to enable Automatic Equation Numbering.
For Sphinx versions below 4.0.0, which used MathJax version 2, the relevant configuration value was called mathjax_config
.
pygments_style
#
Use pygments_style to change the color/font theme that’s used for syntax highlighting in source code.
This affects both code cells and code blocks in Markdown cells (unless overwritten by the html_theme).
suppress_warnings
#
Warnings can be really helpful to detect small mistakes, and you should consider invoking Sphinx with the -W option, which turns warnings into errors. However, warnings can also be annoying, especially if you are fully aware of the “problem”, but you simply don’t care about it for some reason. In this case, you can use suppress_warnings to silence specific types of warnings.
If you want to suppress all warnings from nbsphinx
, use this:
suppress_warnings = [
'nbsphinx',
]
You can also be more specific:
suppress_warnings = [
'nbsphinx.localfile',
'nbsphinx.gallery',
'nbsphinx.thumbnail',
'nbsphinx.notebooktitle',
'nbsphinx.ipywidgets',
]
nbsphinx
Configuration Values#
nbsphinx_allow_errors
#
If True
, the build process is continued even if an exception occurs.
See Ignoring Errors.
nbsphinx_assume_equations
#
If False
, do not force loading MathJax on HTML pages generated from notebooks.
nbsphinx_codecell_lexer
#
Default Pygments lexer for syntax highlighting in code cells. If available, this information is taken from the notebook metadata instead.
nbsphinx_custom_formats
#
nbsphinx_epilog
#
See Prolog and Epilog.
nbsphinx_execute
#
Whether to execute notebooks before conversion or not. Possible values: 'always'
, 'never'
, 'auto'
(default).
nbsphinx_execute_arguments
#
Kernel arguments used when executing notebooks.
nbsphinx_input_prompt
#
Input prompt for code cells. %s
is replaced by the execution count.
To get a prompt similar to the Classic Notebook, use
nbsphinx_input_prompt = 'In [%s]:'
nbsphinx_kernel_name
#
Use a different kernel than stored in the notebook metadata, e.g.:
nbsphinx_kernel_name = 'python3'
nbsphinx_output_prompt
#
Output prompt for code cells. %s
is replaced by the execution count.
To get a prompt similar to the Classic Notebook, use
nbsphinx_output_prompt = 'Out[%s]:'
nbsphinx_prolog
#
See Prolog and Epilog.
nbsphinx_prompt_width
#
Width of input/output prompts (HTML only).
If a prompt is wider than that, it protrudes into the left margin.
Any CSS length can be specified.
nbsphinx_requirejs_options
#
Options for loading RequireJS. See nbsphinx_requirejs_path.
nbsphinx_requirejs_path
#
URL or local path to override the default URL for RequireJS.
If you use a local file, it should be located in a directory listed in html_static_path.
Set to empty string to disable loading RequireJS.
nbsphinx_responsive_width
#
If the browser window is narrower than this, input/output prompts are on separate lines (HTML only).
Any CSS length can be specified.
nbsphinx_thumbnails
#
A dictionary mapping from a document name (i.e. source file without suffix but with subdirectories) – optionally containing wildcards – to a thumbnail path to be used in a thumbnail gallery. Thumbnails specified in notebooks will override those provided in this dictionary.
nbsphinx_timeout
#
Controls when a cell will time out. The timeout is given in seconds. Given -1
, cells will never time out, which is also the default.
nbsphinx_widgets_options
#
Options for loading Jupyter widgets resources. See nbsphinx_widgets_path.
nbsphinx_widgets_path
#
URL or local path to override the default URL for Jupyter widgets resources. See Interactive Widgets (HTML only).
If you use a local file, it should be located in a directory listed in html_static_path.
For loading the widgets resources, RequireJS is needed, see nbsphinx_requirejs_path.
If nbsphinx_widgets_path
is not specified, widgets resources are only loaded if at least one notebook actually uses widgets. If you are loading the relevant JavaScript code by some other means already, you can set this option to the empty string to avoid loading it a second time.
Markdown Cells#
We can use emphasis, boldface, preformatted text
.
It looks like strike-out text is not supported: [STRIKEOUT:strikethrough].
Red
Green
Blue
Note: JupyterLab and JupyterNotebook uses a different Markdown parser than nbsphinx (which currently uses Pandoc). In case that your Bulletpoints do render in the notebook and do not render with nbsphinx, please add one blank line before the bulletpoints. ***
One
Two
Three
Arbitrary Unicode characters should be supported, e.g. łßō. Note, however, that this only works if your HTML browser and your LaTeX processor provide the appropriate fonts.
Equations#
Inline equations like \(\text{e}^{i\pi} = -1\) can be created by putting a LaTeX expression between two dollar signs, like this: $\text{e}^{i\pi} = -1$
.
Note
Avoid leading and trailing spaces around math expressions, otherwise errors like the following will occur when Sphinx is running:
ERROR: Unknown interpreted text role "raw-latex".
See also the pandoc docs:
Anything between two
$
characters will be treated as TeX math. The opening$
must have a non-space character immediately to its right, while the closing$
must have a non-space character immediately to its left, and must not be followed immediately by a digit.
Equations can also be displayed on their own line like this: \begin{equation} \int\limits_{-\infty}^\infty f(x) \delta(x - x_0) dx = f(x_0). \end{equation}
This can be done by simply using one of the LaTeX math environments, like so:
\begin{equation}
\int\limits_{-\infty}^\infty f(x) \delta(x - x_0) dx = f(x_0)
\end{equation}
Note
For equations to be shown in HTML output, you have to specify a math extension in your extensions setting, e.g.:
extensions = [
'nbsphinx',
'sphinx.ext.mathjax',
# ... other useful extensions ...
]
Automatic Equation Numbering#
This is not automatically enabled in Jupyter notebooks, but you can install a notebook extension in order to enable equation numbering: https://jupyter-contrib-nbextensions.readthedocs.io/en/latest/nbextensions/equation-numbering/readme.html.
Automatic Equation Numbering is enabled on https://nbviewer.jupyter.org/, see e.g. the latest version of this very notebook at the link https://nbviewer.jupyter.org/github/spatialaudio/nbsphinx/blob/master/doc/markdown-cells.ipynb#Automatic-Equation-Numbering.
When using nbsphinx
, you can use the following mathjax3_config
setting in your conf.py
file to enable automatic equation numbering in HTML output.
mathjax3_config = {
'tex': {'tags': 'ams', 'useLabelIds': True},
}
This works for Sphinx version 4 (and higher), which uses MathJax version 3. For older Sphinx versions, the corresponding configuration looks like this:
mathjax_config = {
'TeX': {'equationNumbers': {'autoNumber': 'AMS', 'useLabelIds': True}},
}
In LaTeX output, the equations are numbered by default.
You can use \label{...}
to give a unique label to an equation:
\begin{equation} \phi = \frac{1 + \sqrt{5}}{2} \label{golden-mean} \end{equation}
\begin{equation}
\phi = \frac{1 + \sqrt{5}}{2}
\label{golden-mean}
\end{equation}
If automatic equation numbering is enabled, you can later reference that equation using its label. You can use \eqref{golden-mean}
for a reference with parentheses: \eqref{golden-mean}, or \ref{golden-mean}
for a reference without them: \ref{golden-mean}.
In HTML output, these equation references only work for equations within a single HTML page. In LaTeX output, equations from other notebooks can be referenced, e.g. \eqref{fibonacci-recurrence}.
Manual Equation Numbering#
If you prefer to assign equation numbers (or some kind of names) manually, you can do so with \tag{...}
:
\begin{equation} a^2 + b^2 = c^2 \tag{99.4} \label{pythagoras} \end{equation}
\begin{equation}
a^2 + b^2 = c^2
\tag{99.4}
\label{pythagoras}
\end{equation}
The above equation has the number \ref{pythagoras}.
Citations#
According to https://nbconvert.readthedocs.io/en/latest/latex_citations.html, nbconvert
supports citations using a special HTML-based syntax. nbsphinx
supports the same syntax.
Example: [Kluyver et al., 2016].
<cite data-cite="kluyver2016jupyter">(Kluyver et al. 2016)</cite>
You don’t actually have to use <cite>
, any inline HTML tag can be used, e.g. <strong>
: [Pérez et al., 2011].
<strong data-cite="perez2011python">Python: An Ecosystem for Scientific Computing</strong>
In-text citations like Kluyver et al. [2016] can be created like this:
<cite data-cite-t="kluyver2016jupyter">Kluyver et al. (2016)</cite>
You’ll also have to define a list of references, see the section about references.
There is also a Notebook extension which may or may not be useful: https://github.com/takluyver/cite2c.
Footnote citations#
Since version 2.0.0
of sphinxcontrib-bibtex, footnote citations are possible. This generates footnotes for all foot-citations up to the point of the bibliography directive, which is typically placed at the end of the source file.
Depending on whether the documentation is rendered into HTML or into LaTeX/PDF, the citations are either placed into a bibliography as ordinary citations (HTML output) or placed into the footnotes of the citation’s respective page (PDF).
Example: [1].
<cite data-footcite="perez2011python">(Pérez et al. 2011)</cite>
Example for an in-text citation: Pérez et al.[1].
<cite data-footcite-t="perez2011python">Pérez et al. (2011)</cite>
As footnote references are restricted to their own Jupyter notebook or other source file, a raw nbconvert cell of reST format (see the section about raw cells) can be added to the notebook, containing the
.. footbibliography::
directive.
Alternatively, one can use the nbsphinx epilog by setting it to, e.g.,
nbsphinx_epilog = r"""
.. footbibliography::
"""
Code#
We can also write code with nice syntax highlighting:
print("Hello, world!")
Tables#
A |
B |
A and B |
---|---|---|
False |
False |
False |
True |
False |
False |
False |
True |
False |
True |
True |
True |
Images#
Local image:

Remote image:

Using the HTML <img>
tag#
The aforementioned Markdown syntax for including images doesn’t allow specifying the image size.
If you want to control the size of the included image, you can use the HTML <img> element with the width
attribute like this:
<img src="images/notebook_icon.png" alt="Jupyter notebook icon" width="300">
In addition to the src
, alt
, width
and height
attributes, you can also use the class
attribute, which is simply forwarded to the HTML output (and ignored in LaTeX output). All other attributes are ignored.
SVG support for LaTeX#
LaTeX doesn’t support SVG images, but there are Sphinx extensions that can be used for automatically converting SVG images for inclusion in LaTeX output.
Just include one of the following options in the list of extensions in your conf.py
file.
'sphinxcontrib.inkscapeconverter'
or'sphinxcontrib.rsvgconverter'
: See https://github.com/missinglinkelectronics/sphinxcontrib-svg2pdfconverter for installation instructions.The external programs
inkscape
orrsvg-convert
(Debian/Ubuntu packagelibrsvg2-bin
;conda
packagelibrsvg
) are needed, respectively.'sphinx.ext.imgconverter'
: This is a built-in Sphinx extension, see https://www.sphinx-doc.org/en/master/usage/extensions/imgconverter.html.This needs the external program
convert
from ImageMagick.The disadvantage of this extension is that SVGs are converted to bitmap images.
If one of those extensions is installed, SVG images can be used even for LaTeX output:

Remote SVG images can also be used (and will be shown in the LaTeX output):

Cell Attachments#
Images can also be embedded in the notebook itself. Just drag an image file into the Markdown cell you are just editing or copy and paste some image data from an image editor/viewer.
The generated Markdown code will look just like a “normal” image link, except that it will have an attachment:
prefix:

These are cell attachments:
In the Jupyter Notebook, there is a speciall “Attachments” cell toolbar which you can use to see all attachments of a cell and delete them, if needed.
HTML Elements (HTML only)#
It is allowed to use plain HTML elements within Markdown cells. Those elements are passed through to the HTML output and are ignored for the LaTeX output. Below are a few examples.
HTML5 audio elements can be created like this:
<audio src="https://example.org/audio.ogg" controls>alternative text</audio>
Example:
HTML5 video elements can be created like this:
<video src="https://example.org/video.ogv" controls>alternative text</video>
Example:
The alternative text is shown in browsers that don’t support those elements. The same text is also shown in Sphinx’s LaTeX output.
Note: You can also use local files for the <audio>
and <video>
elements, but you have to create a link to the source file somewhere, because only then are the local files copied to the HTML output directory! You should do that anyway to make the audio/video file accessible to browsers that don’t support the <audio>
and <video>
elements.
Info/Warning Boxes#
Warning
This is an experimental feature! Its usage will probably change in the future or it might be removed completely!
Until there is an info/warning extension for Markdown/CommonMark (see this issue), such boxes can be created by using HTML <div>
elements like this:
<div class="alert alert-info">
Note
This is a note!
</div>
For this to work reliably, you should obey the following guidelines:
The
class
attribute has to be either"alert alert-info"
or"alert alert-warning"
, other values will not be converted correctly.No further attributes are allowed.
For compatibility with CommonMark, you should add an empty line between the
<div>
start tag and the beginning of the content.
Warning
While this works nicely with nbsphinx
, JupyterLab and the Classic Jupyter Notebook, This doesn’t work correctly in nbconvert
and by extension on https://nbviewer.jupyter.org/ and Github’s notebook preview.
Note
The text can contain further Markdown formatting. It is even possible to have nested boxes:
… but please don’t overuse this!
Links to Other Notebooks#
Relative links to local notebooks can be used: a link to a notebook in a subdirectory, a link to an orphan notebook (latter won’t work in LaTeX output, because orphan pages are not included there).
This is how a link is created in Markdown:
[a link to a notebook in a subdirectory](subdir/a-notebook-in-a-subdir.ipynb)
Markdown also supports reference-style links: a reference-style link, another version of the same link.
These can be created with this syntax:
[a reference-style link][mylink]
[mylink]: subdir/a-notebook-in-a-subdir.ipynb
Links to sub-sections are also possible, e.g. this subsection.
This link was created with:
[this subsection](subdir/a-notebook-in-a-subdir.ipynb#A-Sub-Section)
You just have to remember to replace spaces with hyphens!
And if there are double quotes in the section title, you’ll have to replace them with %22
, like e.g. #That's-a-%22Strange%22-Section
in this link: a section with “strange” characters.
BTW, links to sections of the current notebook work, too, e.g. beginning of this section.
This can be done, as expected, like this:
[beginning of this section](#Links-to-Other-Notebooks)
It’s also possible to create a link to the beginning of the current page, by simply using a #
character:
[link to the beginning of the current page](#)
Links to *.rst
Files (and Other Sphinx Source Files)#
Links to files whose extension is in the configuration value source_suffix, will be converted to links to the generated HTML/LaTeX pages. Example: A reStructuredText file.
This was created with:
[A reStructuredText file](a-normal-rst-file.rst)
Links to sub-sections are also possible. Example: Sphinx Directives.
This was created with:
[Sphinx Directives](a-normal-rst-file.rst#sphinx-directives-for-info-warning-boxes)
Note
Sphinx section anchors are different from Jupyter section anchors! To create a link to a subsection in an .rst
file (or another non-notebook source file), you not only have to replace spaces with hyphens, but also slashes and some other characters. In case of doubt, just check the target HTML page generated by Sphinx.
Links to Local Files#
Links to local files (other than Jupyter notebooks and other Sphinx source files) are also possible, e.g. requirements.txt.
This was simply created with:
[requirements.txt](requirements.txt)
The linked files are automatically copied to the HTML output directory. For LaTeX output, links are created, but the files are not copied to the target directory.
Links to Domain Objects#
Links to Sphinx domain objects (such as a Python class or JavaScript function) are also possible. For example: example_python_function().
This was created with:
[example_python_function()](a-normal-rst-file.rst#example_python_function)
This is especially useful for use with the Sphinx autodoc extension!
In some situations, you might prefer to have the default Sphinx formatting and checking in place when linking to domain objects. In such a case, raw cells in “reST” format could be an alternative worthwhile considering. They allow one to use any kind of Sphinx roles and directives inside a Jupyter Notebook.
Code Cells#
Code, Output, Streams#
An empty code cell:
[ ]:
Two empty lines:
[ ]:
Leading/trailing empty lines:
[1]:
# 2 empty lines before, 1 after
A simple output:
[2]:
6 * 7
[2]:
42
The standard output stream:
[3]:
print('Hello, world!')
Hello, world!
Normal output + standard output
[4]:
print('Hello, world!')
6 * 7
Hello, world!
[4]:
42
The standard error stream is highlighted and displayed just below the code cell. The standard output stream comes afterwards (with no special highlighting). Finally, the “normal” output is displayed.
[5]:
import sys
print("I'll appear on the standard error stream", file=sys.stderr)
print("I'll appear on the standard output stream")
"I'm the 'normal' output"
I'll appear on the standard output stream
I'll appear on the standard error stream
[5]:
"I'm the 'normal' output"
Note
Using the IPython kernel, the order is actually mixed up, see https://github.com/ipython/ipykernel/issues/280.
Special Display Formats#
Local Image Files#
[6]:
from IPython.display import Image
i = Image(filename='images/notebook_icon.png')
i
[6]:

[7]:
display(i)

See also SVG support for LaTeX.
[8]:
from IPython.display import SVG
SVG(filename='images/python_logo.svg')
[8]:
Image URLs#
[9]:
Image(url='https://www.python.org/static/img/python-logo-large.png')
[9]:

[10]:
Image(url='https://www.python.org/static/img/python-logo-large.png', embed=True)
[10]:

[11]:
Image(url='https://jupyter.org/assets/homepage/main-logo.svg')
[11]:
Math#
[12]:
from IPython.display import Math
eq = Math(r'\int\limits_{-\infty}^\infty f(x) \delta(x - x_0) dx = f(x_0)')
eq
[12]:
[13]:
display(eq)
[14]:
from IPython.display import Latex
Latex(r'This is a \LaTeX{} equation: $a^2 + b^2 = c^2$')
[14]:
[15]:
%%latex
\begin{equation}
\int\limits_{-\infty}^\infty f(x) \delta(x - x_0) dx = f(x_0)
\end{equation}
Plots#
Make sure to use at least version 0.1.6 of the matplotlib-inline
package (which is an automatic dependency of the ipython
package).
By default, the plots created with the “inline” backend have the wrong size. More specifically, PNG plots (the default) will be slightly larger than SVG and PDF plots.
This can be fixed easily by creating a file named matplotlibrc
(in the directory where your Jupyter notebooks live, e.g. in this directory: matplotlibrc) and adding the following line:
figure.dpi: 96
If you are using Git to manage your files, don’t forget to commit this local configuration file to your repository. Different directories can have different local configurations. If a given configuration should apply to multiple directories, symbolic links can be created in each directory.
For more details, see Default Values for Matplotlib’s “inline” Backend.
By default, plots are generated in the PNG format. In most cases, it looks better if SVG plots are used for HTML output and PDF plots are used for LaTeX/PDF. This can be achieved by setting nbsphinx_execute_arguments in your conf.py
file like this:
nbsphinx_execute_arguments = [
"--InlineBackend.figure_formats={'svg', 'pdf'}",
]
In the following example, nbsphinx
should use an SVG image in the HTML output and a PDF image for LaTeX/PDF output (other Jupyter clients like JupyterLab will still show the default PNG format).
[16]:
import matplotlib.pyplot as plt
[17]:
fig, ax = plt.subplots(figsize=[6, 3])
ax.plot([4, 9, 7, 20, 6, 33, 13, 23, 16, 62, 8]);
For comparison, this is how it would look in PNG format …
[18]:
%config InlineBackend.figure_formats = ['png']
[19]:
fig
[19]:

… and in 'png2x'
(a.k.a. 'retina'
) format:
[20]:
%config InlineBackend.figure_formats = ['png2x']
[21]:
fig
[21]:

Instead of the default inline
plotting backend, you can also use the widget
backend (which needs the ipympl
package to be installed):
[22]:
%matplotlib widget
[23]:
fig, ax = plt.subplots(figsize=[6, 3])
ax.plot([4, 9, 7, 20, 6, 33, 13, 23, 16, 62, 8]);
Pandas Dataframes#
Pandas dataframes should be displayed as nicely formatted HTML tables (if you are using HTML output).
[24]:
import numpy as np
import pandas as pd
[25]:
df = pd.DataFrame(np.random.randint(0, 100, size=[10, 4]),
columns=[r'$\alpha$', r'$\beta$', r'$\gamma$', r'$\delta$'])
df
[25]:
$\alpha$ | $\beta$ | $\gamma$ | $\delta$ | |
---|---|---|---|---|
0 | 41 | 61 | 38 | 76 |
1 | 40 | 23 | 69 | 99 |
2 | 58 | 13 | 99 | 84 |
3 | 81 | 17 | 75 | 17 |
4 | 0 | 87 | 47 | 26 |
5 | 81 | 56 | 38 | 91 |
6 | 92 | 95 | 63 | 38 |
7 | 58 | 47 | 17 | 23 |
8 | 90 | 39 | 27 | 59 |
9 | 82 | 50 | 77 | 73 |
Markdown Content#
[26]:
from IPython.display import Markdown
[27]:
md = Markdown("""
# Markdown
It *should* show up as **formatted** text
with things like [links] and images.
[links]: https://jupyter.org/

## Markdown Extensions
There might also be mathematical equations like
$a^2 + b^2 = c^2$
and even tables:
A | B | A and B
------|-------|--------
False | False | False
True | False | False
False | True | False
True | True | True
""")
md
YouTube Videos#
[28]:
from IPython.display import YouTubeVideo
YouTubeVideo('9_OIs49m56E')
[28]:
Interactive Widgets (HTML only)#
The basic widget infrastructure is provided by the ipywidgets module. More advanced widgets are available in separate packages, see for example https://jupyter.org/widgets.
The JavaScript code which is needed to display Jupyter widgets is loaded automatically (using RequireJS). If you want to use non-default URLs or local files, you can use the nbsphinx_widgets_path and nbsphinx_requirejs_path settings.
[29]:
import ipywidgets as w
[30]:
slider = w.IntSlider()
slider.value = 42
slider
[30]:
A widget typically consists of a so-called “model” and a “view” into that model.
If you display a widget multiple times, all instances act as a “view” into the same “model”. That means that their state is synchronized. You can move either one of these sliders to try this out:
[31]:
slider
[31]:
You can also link different widgets.
Widgets can be linked via the kernel (which of course only works while a kernel is running) or directly in the client (which even works in the rendered HTML pages).
Widgets can be linked uni- or bi-directionally.
Examples for all 4 combinations are shown here:
[32]:
link = w.IntSlider(description='link')
w.link((slider, 'value'), (link, 'value'))
jslink = w.IntSlider(description='jslink')
w.jslink((slider, 'value'), (jslink, 'value'))
dlink = w.IntSlider(description='dlink')
w.dlink((slider, 'value'), (dlink, 'value'))
jsdlink = w.IntSlider(description='jsdlink')
w.jsdlink((slider, 'value'), (jsdlink, 'value'))
w.VBox([link, jslink, dlink, jsdlink])
[32]:
[33]:
tabs = w.Tab()
for idx, obj in enumerate([df, fig, eq, i, md, slider]):
out = w.Output()
with out:
display(obj)
tabs.children += out,
tabs.set_title(idx, obj.__class__.__name__)
tabs
[33]:
Other Languages
The examples shown here are using Python, but the widget technology can also be used with different Jupyter kernels (i.e. with different programming languages).
Troubleshooting#
To obtain more information if widgets are not displayed as expected, you will need to look at the error message in the web browser console.
To figure out how to open the web browser console, you may look at the web browser documentation:
The error is most probably linked to the JavaScript files not being loaded or loaded in the wrong order within the HTML file. To analyze the error, you can inspect the HTML file within the web browser (e.g.: right-click on the page and select View Page Source) and look at the <head>
section of the page. That section should contain some JavaScript libraries. Those relevant for widgets are:
<!-- require.js is a mandatory dependency for jupyter-widgets -->
<script crossorigin="anonymous" integrity="sha256-Ae2Vz/4ePdIu6ZyI/5ZGsYnb+m0JlOmKPjt6XZ9JJkA=" src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js"></script>
<!-- jupyter-widgets JavaScript -->
<script type="text/javascript" src="https://unpkg.com/@jupyter-widgets/html-manager@^0.18.0/dist/embed-amd.js"></script>
<!-- JavaScript containing custom Jupyter widgets -->
<script src="../_static/embed-widgets.js"></script>
The two first elements are mandatory. The third one is required only if you designed your own widgets but did not publish them on npm.js.
If those libraries appear in a different order, the widgets won’t be displayed.
Here is a list of possible solutions:
Arbitrary JavaScript Output (HTML only)#
[34]:
%%javascript
var text = document.createTextNode("Hello, I was generated with JavaScript!");
// Content appended to "element" will be visible in the output area:
element.appendChild(text);
Unsupported Output Types#
If a code cell produces data with an unsupported MIME type, the Jupyter Notebook doesn’t generate any output. nbsphinx
, however, shows a warning message.
[35]:
display({
'text/x-python': 'print("Hello, world!")',
'text/x-haskell': 'main = putStrLn "Hello, world!"',
}, raw=True)
Data type cannot be displayed: text/x-python, text/x-haskell
ANSI Colors#
The standard output and standard error streams may contain ANSI escape sequences to change the text and background colors.
[36]:
print('BEWARE: \x1b[1;33;41mugly colors\x1b[m!', file=sys.stderr)
print('AB\x1b[43mCD\x1b[35mEF\x1b[1mGH\x1b[4mIJ\x1b[7m'
'KL\x1b[49mMN\x1b[39mOP\x1b[22mQR\x1b[24mST\x1b[27mUV')
ABCDEFGHIJKLMNOPQRSTUV
BEWARE: ugly colors!
The following code showing the 8 basic ANSI colors is based on https://web.archive.org/web/20231225185739/https://tldp.org/HOWTO/Bash-Prompt-HOWTO/x329.html. Each of the 8 colors has an “intense” variation, which is used for bold text.
[37]:
text = ' XYZ '
formatstring = '\x1b[{}m' + text + '\x1b[m'
print(' ' * 6 + ' ' * len(text) +
''.join('{:^{}}'.format(bg, len(text)) for bg in range(40, 48)))
for fg in range(30, 38):
for bold in False, True:
fg_code = ('1;' if bold else '') + str(fg)
print(' {:>4} '.format(fg_code) + formatstring.format(fg_code) +
''.join(formatstring.format(fg_code + ';' + str(bg))
for bg in range(40, 48)))
40 41 42 43 44 45 46 47
30 XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ
1;30 XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ
31 XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ
1;31 XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ
32 XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ
1;32 XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ
33 XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ
1;33 XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ
34 XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ
1;34 XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ
35 XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ
1;35 XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ
36 XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ
1;36 XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ
37 XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ
1;37 XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ XYZ
ANSI also supports a set of 256 indexed colors. The following code showing all of them is based on http://bitmote.com/index.php?post/2012/11/19/Using-ANSI-Color-Codes-to-Colorize-Your-Bash-Prompt-on-Linux.
[38]:
formatstring = '\x1b[38;5;{0};48;5;{0}mX\x1b[1mX\x1b[m'
print(' + ' + ''.join('{:2}'.format(i) for i in range(36)))
print(' 0 ' + ''.join(formatstring.format(i) for i in range(16)))
for i in range(7):
i = i * 36 + 16
print('{:3} '.format(i) + ''.join(formatstring.format(i + j)
for j in range(36) if i + j < 256))
+ 0 1 2 3 4 5 6 7 8 91011121314151617181920212223242526272829303132333435
0 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
16 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
52 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
88 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
124 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
160 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
196 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
232 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
You can even use 24-bit RGB colors:
[39]:
start = 255, 0, 0
end = 0, 0, 255
length = 79
out = []
for i in range(length):
rgb = [start[c] + int(i * (end[c] - start[c]) / length) for c in range(3)]
out.append('\x1b['
'38;2;{rgb[2]};{rgb[1]};{rgb[0]};'
'48;2;{rgb[0]};{rgb[1]};{rgb[2]}mX\x1b[m'.format(rgb=rgb))
print(''.join(out))
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Raw Cells#
Any Jupyter Notebook consists of cells of three different types: Code cells, Markdown cells , and/or Raw cells. While most Jupyter Notebook users are very familiar with Code cells and Markdown cells in Jupyter Notebooks, Raw cells are less frequently used. For Jupyter Notebook, they are introduced here and for JupyterLab here. The Raw cells are also sometimes referred to as Raw NBConvert cells in the context of nbconvert. The Raw cell type can be used to render different code formats into HTML or LaTeX by Sphinx. This information is stored in the notebook metadata and converted appropriately.
Usage#
Raw cells are created differently depending on the user interface.
Jupyter Notebook#
To select a desired format from within Jupyter Notebook, select the cell containing your special code and choose options from the following dropdown menus:
Select “Raw NBConvert” in the Menu Toolbar (just below the two menus “Widgets” and “Help”).
Click on the “Raw NBConvert Format” dropdown menu within the cell and select “reST”.
JupyterLab#
To select a desired format from within JupyterLab, first activate the right sidebar by clicking on View in the Menu Toolbar. Then you ensure that in front of Show Right Sidebar there is a tick. Once the Right Sidebar is shown, you are ready to go.
Now you select the cell containing your special code and choose options from the following dropdown menus:
Select “Raw” in the Notebook Toolbar (just next to the symbols that run cells or reload the kernel).
Click on “Raw NBConvert Format” in the Right Sidebar and select “reStructured Text”.
Available Raw Cell Formats#
The following examples show how different Jupyter cell formats are rendered by Sphinx.
None#
By default (if no cell format is selected), the cell content is included (without any conversion) in both the HTML and LaTeX output. This is typically not useful at all.
"I'm a raw cell with no format."reST#
Raw cells in “reST” format are interpreted as reStructuredText and parsed by Sphinx. Thus, you can e.g. use its cross-referencing abilities for automatically creating/updating links to the definition of modules, classes, functions, and similar. The result is visible in both HTML and LaTeX output.
“I’m a raw cell in reST format.”
I can contain Sphinx roles such as a link to example_python_function()
.
Markdown#
Raw cells in “Markdown” format are interpreted as Markdown, and the result is included in both HTML and LaTeX output. Since the Jupyter Notebook also supports normal Markdown cells, this might not be useful at all.
“I’m a raw cell in Markdown format.”
HTML#
Raw cells in “HTML” format are only visible in HTML output. This option might not be very useful, since raw HTML code is also allowed within normal Markdown cells.
“I’m a raw cell in HTML format.”
LaTeX#
Raw cells in “LaTeX” format are only visible in LaTeX output.
Python#
Raw cells in “Python” format are not visible at all (nor executed in any way).
Hidden Cells#
You can remove cells from the HTML/LaTeX output by adding this to the cell metadata:
"nbsphinx": "hidden"
Hidden cells are still executed but removed afterwards.
For example, the following hidden cell defines the variable answer
.
This is the cell after the hidden cell. Although the previous cell is not visible, its result is still available:
[2]:
answer
[2]:
42
Don’t overuse this, because it may make it harder to follow what’s going on in your notebook.
Also Markdown cells can be hidden. The following cell is hidden.
This is the cell after the hidden cell.
Controlling Notebook Execution#
Notebooks with no outputs are automatically executed during the Sphinx build process. If, however, there is at least one output cell present, the notebook is not evaluated and included as is.
The following notebooks show how this default behavior can be used and customized.
Pre-Executing Notebooks#
Automatically executing notebooks during the Sphinx build process is an important feature of nbsphinx
. However, there are a few use cases where pre-executing a notebook and storing the outputs might be preferable. Storing any output will, by default, stop nbsphinx
from executing the notebook.
Long-Running Cells#
If you are doing some very time-consuming computations, it might not be feasible to re-execute the notebook every time you build your Sphinx documentation.
So just do it once – when you happen to have the time – and then just keep the output.
[1]:
import time
[2]:
%time time.sleep(60 * 60)
6 * 7
CPU times: user 160 ms, sys: 56 ms, total: 216 ms
Wall time: 1h 1s
[2]:
42
Rare Libraries#
You might have created results with a library that’s hard to install and therefore you have only managed to install it on one very old computer in the basement, so you probably cannot run this whenever you build your Sphinx docs.
[3]:
from a_very_rare_library import calculate_the_answer
[4]:
calculate_the_answer()
[4]:
42
Exceptions#
If an exception is raised during the Sphinx build process, it is stopped (the build process, not the exception!). If you want to show to your audience how an exception looks like, you have two choices:
Allow errors – either generally or on a per-notebook or per-cell basis – see Ignoring Errors (per cell).
Execute the notebook beforehand and save the results, like it’s done in this example notebook:
[5]:
1 / 0
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
<ipython-input-5-b710d87c980c> in <module>()
----> 1 1 / 0
ZeroDivisionError: division by zero
Client-specific Outputs#
When nbsphinx
executes notebooks, it uses the nbconvert
module to do so. Certain Jupyter clients might produce output that differs from what nbconvert
would produce. To preserve those original outputs, the notebook has to be executed and saved before running Sphinx.
For example, the JupyterLab help system shows the help text as cell outputs, while executing with nbconvert
doesn’t produce any output.
[6]:
sorted?
Signature: sorted(iterable, /, *, key=None, reverse=False)
Docstring:
Return a new list containing all items from the iterable in ascending order.
A custom key function can be supplied to customize the sort order, and the
reverse flag can be set to request the result in descending order.
Type: builtin_function_or_method
Interactive Input#
If your code asks for user input, it probably doesn’t work when executed by Sphinx/nbsphinx
. You’ll probably get an error like this:
StdinNotImplementedError: raw_input was called, but this frontend does not support input requests.
In this case, you can run the notebook interactively, provide the desired inputs and then save the notebook including its cell outputs.
[7]:
name = input('What... is your name?')
quest = input('What... is your quest?')
color = input('What... is your favorite color?')
What... is your name? Sir Lancelot of Camelot
What... is your quest? To seek the Holy Grail
What... is your favorite color? Blue
Explicitly Dis-/Enabling Notebook Execution#
If you want to include a notebook without outputs and yet don’t want nbsphinx
to execute it for you, you can explicitly disable this feature.
You can do this globally by setting the following option in conf.py:
nbsphinx_execute = 'never'
Or on a per-notebook basis by adding this to the notebook’s JSON metadata:
"nbsphinx": {
"execute": "never"
},
There are three possible settings, "always"
, "auto"
and "never"
. By default (= "auto"
), notebooks with no outputs are executed and notebooks with at least one output are not. As always, per-notebook settings take precedence over the settings in conf.py
.
This very notebook has its metadata set to "never"
, therefore the following cell is not executed:
[ ]:
6 * 7
Ignoring Errors#
Normally, if an exception is raised while executing a notebook, the Sphinx build process is stopped immediately.
If a notebook contains errors on purpose (or if you are too lazy to fix them right now), you have four options:
Manually execute the notebook in question and save the results, see the pre-executed example notebook.
Allow errors in all notebooks by setting this option in conf.py:
nbsphinx_allow_errors = True
Allow errors on a per-notebook basis by adding this to the notebook’s JSON metadata:
"nbsphinx": { "allow_errors": true },
Allow errors on a per-cell basis using the
raises-exception
tag, see Ignoring Errors on a Cell-by-Cell Basis.
This very notebook is an example for the third option. The results of the following code cells are not stored within the notebook, therefore it is executed during the Sphinx build process. Since the above-mentioned allow_errors
flag is set in this notebook’s metadata, all cells are executed although most of them cause an exception.
[1]:
nonsense
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[1], line 1
----> 1 nonsense
NameError: name 'nonsense' is not defined
[2]:
42 / 0
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
Cell In[2], line 1
----> 1 42 / 0
ZeroDivisionError: division by zero
[3]:
6 * 7
[3]:
42
Ignoring Errors on a Per-Cell Basis#
Instead of ignoring errors for all notebooks or for some selected notebooks (see the previous notebook), you can be more fine-grained and just allow errors on certain code cells by tagging them with the raises-exception
tag.
[1]:
'no problem'
[1]:
'no problem'
The following code cell has the raises-exception
tag.
[2]:
problem
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[2], line 1
----> 1 problem
NameError: name 'problem' is not defined
The following code cell is executed even though the previous cell raised an exception.
[3]:
'no problem'
[3]:
'no problem'
Note
The behavior of the raises-exception
tag doesn’t match its name. While it does allow exceptions, it does not check if an exception is actually raised!
This will hopefully be fixed at some point, see https://github.com/jupyter/nbconvert/issues/730.
Configuring the Kernels#
Kernel Name#
If we have multiple kernels installed, we can choose to override the kernel saved in the notebook using nbsphinx_kernel_name:
nbsphinx_kernel_name = 'python-upstream-dev'
which uses the kernel named python-upstream-dev
instead of the kernel name stored in the notebook.
Kernel Arguments#
We can pass arguments to the kernel by using nbsphinx_execute_arguments, for example to set plot options:
nbsphinx_execute_arguments = [
"--InlineBackend.figure_formats={'svg', 'pdf'}",
]
Environment Variables#
The contents of os.environ
after the execution of conf.py
will be passed as environment variables to the kernel. As an example, MY_DUMMY_VARIABLE
has been set in conf.py like this:
import os
os.environ['MY_DUMMY_VARIABLE'] = 'Hello from conf.py!'
… and it can be checked in the notebook like this:
[1]:
import os
os.environ['MY_DUMMY_VARIABLE']
[1]:
'Hello from conf.py!'
This is useful if we want to edit PYTHONPATH
in order to compile the documentation without installing the project:
import os
src = os.path.abspath('../src')
os.environ['PYTHONPATH'] = src
If you are using https://mybinder.org/ and you want to define environment variables, you should create a file .binder/start
in your repository (see Binder docs) containing definitions like this:
#!/bin/bash
export MY_DUMMY_VARIABLE="Hello from .binder/start!"
exec "$@"
Cell Execution Timeout#
By default, code cells will be executed until they are finished, even if that takes a very long time. In some cases they might never finish.
If you would like to only use a finite amount of time per cell, you can choose a timeout length for all notebooks by setting the following option in conf.py:
nbsphinx_timeout = 60
Or change the timeout length on a per-notebook basis by adding this to the notebook’s JSON metadata:
"nbsphinx": {
"timeout": 60
},
The timeout is given in seconds, use -1
to disable the timeout (which is the default).
Alternatively, you can manually execute the notebook in question and save the results, see the pre-executed example notebook.
Prolog and Epilog#
When including notebooks in your Sphinx documentation, you can choose to add some generic content before and after each notebook. This can be done with the configuration values nbsphinx_prolog
and nbsphinx_epilog
in the file conf.py
.
The prolog and epilog strings can hold arbitrary reST markup. Particularly, the only and raw directives can be used to have different content for HTML and LaTeX output.
Those strings are also processed by the Jinja2 templating engine. This means you can run Python-like code within those strings. You have access to the current Sphinx build environment via the variable env
. Most notably, you can get the file name of the current notebook with
{{ env.doc2path(env.docname, base=None) }}
Have a look at the Jinja2 template documentation for more information.
Warning
If you use invalid syntax, you might get an error like this:
jinja2.exceptions.TemplateSyntaxError: expected token ':', got '}'
This is especially prone to happen when using raw LaTeX, with its abundance of braces. To avoid clashing braces you can try to insert additional spaces or LaTeX macros that don’t have a visible effect, like e.g. \strut{}
. For example, you can avoid three consecutive opening braces with something like that:
\texttt{\strut{}{{ env.doc2path(env.docname, base=None) }}}
NB: The three consecutive closing braces in this example are not problematic.
An alternative work-around would be to surround LaTeX braces with Jinja braces like this:
{{ '{' }}
The string within will not be touched by Jinja.
Another special Jinja syntax is {%
, which is also often used in fancy TeX/LaTeX code. A work-around for this situation would be to use
{{ '{%' }}
Examples#
You can include a simple static string, using reST markup if you like:
nbsphinx_epilog = """
----
Generated by nbsphinx_ from a Jupyter_ notebook.
.. _nbsphinx: https://nbsphinx.readthedocs.io/
.. _Jupyter: https://jupyter.org/
"""
Using some additional Jinja2 markup and the information from the env
variable, you can create URLs that point to the current notebook file, but located on some other server:
nbsphinx_prolog = """
Go there: https://example.org/notebooks/{{ env.doc2path(env.docname, base=None) }}
----
"""
You can also use separate content for HTML and LaTeX output, e.g.:
nbsphinx_prolog = r"""
{% set docname = env.doc2path(env.docname, base=None) %}
.. only:: html
Go there: https://example.org/notebooks/{{ docname }}
.. raw:: latex
\nbsphinxstartnotebook{The following section was created from
\texttt{\strut{}{{ docname }}}:}
"""
nbsphinx_epilog = r"""
.. raw:: latex
\nbsphinxstopnotebook{\hfill End of notebook.}
"""
Note the use of the \nbsphinxstartnotebook
and \nbsphinxstopnotebook
commands. Those make sure there is not too much space between the “prolog” and the beginning of the notebook and, respectively, between the end of the notebook and the “epilog”. They also avoid page breaks, in order for the “prolog”/”epilog” not to end up on the page before/after the notebook.
For a more involved example for different HTML and LaTeX versions, see the file conf.py of the nbsphinx
documentation.
Custom Notebook Formats#
By default, Jupyter notebooks are stored in files with the suffix .ipynb
, which use the JSON format for storage.
However, there are libraries available which allow storing notebooks in different formats, using different file suffixes.
To use a custom notebook format in nbsphinx
, you can specify the nbsphinx_custom_formats
option in your conf.py
file. You have to provide the file extension and a conversion function that takes the contents of a file (as a string) and returns a Jupyter notebook object.
nbsphinx_custom_formats = {
'.mysuffix': 'mylibrary.converter_function',
}
The converter function can be given as a string (recommended) or as a function object.
If a conversion function takes more than a single string argument, you can specify the function name plus a dictionary with keyword arguments which will be passed to the conversion function in addition to the file contents.
nbsphinx_custom_formats = {
'.mysuffix': ['mylibrary.converter_function', {'some_arg': 42}],
}
You can of course use multiple formats by specifying multiple conversion functions.
Example: Jupytext#
One example for a library which provides a custom conversion function is jupytext, which allows storing the contents of Jupyter notebooks in Markdown and R-Markdown, as well as plain Julia, Python and R files.
Since its conversion function takes more than a single string argument, we have to pass a keyword argument, e.g.:
nbsphinx_custom_formats = {
'.Rmd': ['jupytext.reads', {'fmt': 'Rmd'}],
}
This very page is an example of a notebook stored in the py:percent
format (see docs):
[1]:
!head -20 custom-formats.pct.py
# %% [markdown]
# # Custom Notebook Formats
#
# By default, Jupyter notebooks are stored in files with the suffix `.ipynb`,
# which use the JSON format for storage.
#
# However, there are libraries available which allow storing notebooks
# in different formats, using different file suffixes.
#
# To use a custom notebook format in `nbsphinx`, you can specify the
# `nbsphinx_custom_formats` option in your `conf.py` file.
# You have to provide the file extension
# and a conversion function that takes the contents of a file (as a string)
# and returns a Jupyter notebook object.
#
# ```python
# nbsphinx_custom_formats = {
# '.mysuffix': 'mylibrary.converter_function',
# }
# ```
To select a suitable conversion function,
we use the following setting in conf.py
:
nbsphinx_custom_formats = {
'.pct.py': ['jupytext.reads', {'fmt': 'py:percent'}],
'.md': ['jupytext.reads', {'fmt': 'Rmd'}],
}
Another example is this gallery example page.
Notebooks in Sub-Directories#
You can organize your notebooks in subdirectories and nbsphinx
will take care that relative links to other notebooks, images and other files still work.
Let’s see if links to local images work:
[1]:
from IPython.display import Image
Image(filename='../images/notebook_icon.png')
[1]:

Warning
There may be problems with images in output cells if your source directory contains symbolic links, see issue #49.
A link to a notebook in the same sub-directory: link.
A link to a notebook in the parent directory: link.
A link to a local file: link.
A random equation: \begin{equation} F_n = F_{n-1} + F_{n-2} \tag{08.15} \label{fibonacci-recurrence} \end{equation}
A Sub-Section#
This is just for testing inter-notebook links, see this section.
That’s a “Strange” Section#
This is for testing links to a section title containing quotes.
Creating Thumbnail Galleries#
Inspired by Sphinx-Gallery, you can create thumbnail galleries from a list of Jupyter notebooks (or other Sphinx source files).
nbsphinx
provides CSS styles for galleries, but like all styles you can tweak them with your own CSS files loaded via html_css_files. If you want to disable all the original styling, you can create a file named nbsphinx-gallery.css
somewhere in your html_static_path, which will replace the original CSS file
(adding it to html_css_files
is not necessary in this case, because it is automatically added by nbsphinx
).
The following sections present two different ways of creating thumbnail galleries in Jupyter notebooks and show how thumbnail images can be selected. Thumbnail galleries can also be created in reStructuredText files.
Gallery With Nested Documents#
You can create thumbnail galleries in reST files, but you can also create such galleries in Jupyter notebooks by adding the nbsphinx-gallery
cell tag or metadata, which is used just like the nbsphinx-toctree cell tag/metadata. For possible options, see the toctree notebook.
Note
In LaTeX output this behaves just like toctree
, i.e. no thumbnail gallery is shown, but the linked files are included in the document.
Like with toctree
you should avoid adding content after a gallery (except other toctrees and galleries) because this content would appear in the LaTeX output after the content of all included source files, which is probably not what you want.
The following cell has the nbsphinx-gallery
tag, which creates a thumbnail gallery. The first section title in that cell (if available) is used as caption
(unless it is already given in the metadata).
The notebooks in the following gallery describe different ways how to select which images are used as thumbnails. The notebooks are added as sub-sections under the current section, just like when using toctree
. If you want to create a gallery from links to notebooks that are already included somewhere else, you can use nbsphinx-link-gallery.
Default Thumbnail#
By default, the last image output of a notebook will be used as its thumbnail. Without an image output, a placeholder will be used. See a notebook with no thumbnail for an example.
However, if a thumbnail is explicitly assigned by Using Cell Metadata to Select a Thumbnail, Using a Cell Tag to Select a Thumbnail or Specifying a Thumbnail File, these methods will take precedence.
[1]:
import matplotlib.pyplot as plt
import numpy as np
Although the next cell contains an image (a plot), it won’t be used as the thumbnail because it’s not the last in the notebook, and we haven’t explicitly tagged it.
[2]:
fig, ax = plt.subplots(figsize=[6, 3])
x = np.linspace(-5, 5, 50)
ax.plot(x, np.sinc(x));
But the next cell is the last containing an image in the notebook, so its last image output will be used as the thumbnail.
[3]:
display(fig)
fig, ax = plt.subplots(figsize=[6, 3])
x = np.linspace(-5, 5, 50)
ax.plot(x, -np.sinc(x), color='red');
Using a Cell Tag to Select a Thumbnail#
You can select any code cell (with appropriate output) by tagging it with the nbsphinx-thumbnail
tag.
If there are multiple outputs in the selected cell, the last one is used. See Choosing from Multiple Outputs for how to select a specific output. If you want to show a tooltip, have a look at Using Cell Metadata to Select a Thumbnail.
[1]:
import matplotlib.pyplot as plt
The following cell has the nbsphinx-thumbnail
tag, which will take precedence over the default of the last image in the notebook:
[2]:
fig, ax = plt.subplots(figsize=[6, 3])
ax.plot([4, 9, 7, 20, 6, 33, 13, 23, 16, 62, 8])
[2]:
[<matplotlib.lines.Line2D at 0x7fcb042eef00>]
Although the next cell has an image, it won’t be used as the thumbnail, due to the tag on the one above.
[3]:
fig, ax = plt.subplots(figsize=[6, 3])
ax.scatter(range(10), [0, 8, 9, 1, -8, -10, -3, 7, 10, 4])
[3]:
<matplotlib.collections.PathCollection at 0x7fcad96ed820>
Using Cell Metadata to Select a Thumbnail#
If the nbsphinx-thumbnail cell tag is not enough, you can use cell metadata to specify more options.
The last cell in this notebook has this metadata:
{
"nbsphinx-thumbnail": {
"tooltip": "This tooltip message was defined in cell metadata"
}
}
If there are multiple outputs in the selected cell, the last one is used. See Choosing from Multiple Outputs for how to select a specific output.
[1]:
import matplotlib.pyplot as plt
import numpy as np
[2]:
plt.rcParams['image.cmap'] = 'coolwarm'
plt.rcParams['image.origin'] = 'lower'
Some example data stolen from https://matplotlib.org/examples/pylab_examples/pcolor_demo.html:
[3]:
x, y = np.meshgrid(np.arange(-3, 3, 0.1), np.arange(-2, 2, 0.1))
z = (1 - x / 2 + x ** 5 + y ** 3) * np.exp(-x ** 2 - y ** 2)
[4]:
zmax = np.max(np.abs(z))
[5]:
fig, ax = plt.subplots(figsize=[5, 3.5])
ax.imshow(z, vmin=-zmax, vmax=zmax)
[5]:
<matplotlib.image.AxesImage at 0x7fceebd03260>
Choosing from Multiple Outputs#
By default, the last output of the selected cell is used as a thumbnail. If that’s what you want, you can simply use the nbsphinx-thumbnail cell tag.
If you want to specify one of multiple outputs, you can add a (zero-based) "output-index"
to your "nbsphinx-thumbnail"
cell metadata.
The following cell has this metadata, selecting the third output to be used as thumbnail in the gallery.
{
"nbsphinx-thumbnail": {
"output-index": 2
}
}
[1]:
from IPython.display import Image
display(Image(url='https://jupyter.org/assets/homepage/main-logo.svg'))
print('Hello!')
display(Image(filename='../images/notebook_icon.png'))
display(Image(url='https://www.python.org/static/img/python-logo-large.png', embed=True))
Hello!


A Notebook without Thumbnail#
This notebook doesn’t contain any thumbnail metadata.
It should be displayed with the default thumbnail image in the gallery.
Specifying Thumbnails in conf.py
#
This notebook doesn’t contain a nbsphinx-thumbnail
cell tag nor cell metadata. Instead, in the file conf.py, a thumbnail is specified (via the nbsphinx_thumbnails option), which will be used in the gallery.
The keys in the nbsphinx_thumbnails
dictionary can contain wildcards, which behave very similarly to the html_sidebars option.
The thumbnail files can be local image files somewhere in the source directory, but you’ll need to create at least one link to them in order to copy them to the HTML output directory.
You can also use files from the _static
directory (which contains all files in your html_static_path).
If you want, you can also use files from the _images
directory, which contains all notebook outputs.
To demonstrate this feature, we are creating an image file here:
[1]:
import matplotlib.pyplot as plt
[2]:
fig, ax = plt.subplots()
ax.plot([4, 8, 15, 16, 23, 42])
fig.savefig('a-local-file.png')
plt.close() # avoid plotting the figure
Please note that the previous cell doesn’t have any outputs, but it has generated a file named a-local-file.png
in the notebook’s directory.
We have to create a link to this file (which is a good idea anyway): a-local-file.png.
Now we can use this file in our conf.py like this:
nbsphinx_thumbnails = {
'gallery/thumbnail-from-conf-py': 'gallery/a-local-file.png',
}
Please note that the notebook name does not contain the .ipynb
suffix.
Note that the following plot is not used as a thumbnail because the nbsphinx_thumbnails
setting overrides the default behavior.
[3]:
fig, ax = plt.subplots(figsize=[6, 3])
ax.plot([4, 9, 7, 20, 6, 33, 13, 23, 16, 62, 8], 'r:');
Gallery With Links (HTML only)#
Contrary to nbsphinx-gallery, the cell tag/metadata nbsphinx-link-gallery
creates a gallery from notebooks (and other source) files without including them as sub-sections. Other than that, it works in a similar way, but only the options "name"
, "caption"
and "reversed"
are supported. In LaTeX output, this has no effect. The cell is ignored and nothing is added to the LaTeX document.
In reST files (and raw reST cells), the nblinkgallery directive can be used.
The following Markdown cell has the nbsphinx-link-gallery
tag, which turns the contained links into a gallery and uses the first section title as caption
:
This is a thumbnail gallery with links to existing documents:
Using toctree
In A Notebook#
In Sphinx-based documentation, there is typically a file called index.rst
which contains one or more toctree directives. Those can be used to pull in further source files (which themselves can contain further toctree
directives).
With nbsphinx
it is possible to get a similar effect within a Jupyter notebook using the nbsphinx-toctree
cell tag or cell metadata. Markdown cells with nbsphinx-toctree
tag/metadata are not converted like “normal” Markdown cells. Instead, they are only scanned for links to other notebooks (or *.rst
files and other Sphinx source files) and those links are added to a toctree
directive. External links can also be used, but they will not be visible in the LaTeX output.
If there is a section title in the selected cell, it is used as toctree
caption (but it also works without a title).
Note
All other content of such a cell is ignored!
If you are satisfied with the default settings, you can simply use nbsphinx-toctree
as a cell tag.
Alternatively, you can store nbsphinx-toctree
cell metadata. Use …
{
"nbsphinx-toctree": {}
}
… for the default settings, …
{
"nbsphinx-toctree": {
"maxdepth": 2
}
}
… for setting the :maxdepth:
option, or…
{
"nbsphinx-toctree": {
"hidden": true
}
}
… for setting the :hidden:
option.
Of course, multiple options can be used at the same time, e.g.
{
"nbsphinx-toctree": {
"maxdepth": 3,
"numbered": true
}
}
For more options, have a look a the Sphinx documentation. All options can be used – except :glob:
, which can only be used in rst files and in raw reST cells.
Note
In HTML output, a toctree
cell generates an in-line table of contents (containing links) at its position in the notebook, whereas in the LaTeX output, a new (sub-)section with the actual content is inserted at its position. All content below the toctree
cell will appear after the table of contents/inserted section, respectively. If you want to use the LaTeX output, it is recommended that you don’t add further cells below a toctree
cell, otherwise their content may appear at
unexpected places. Multiple toctree
cells in a row should be fine, though.
The following cell is tagged with nbsphinx-toctree
and contains a link to the notebook yet-another.ipynb and an external link (which will only be visible in the HTML output). It also contains a section title which will be used as toctree
caption (which also will only be visible in the HTML output).
Yet Another Notebook#
This notebook is only here to show how (sub-)toctrees can be created with Markdown cell metadata. See there.
Custom CSS#
If you are not satisfied with the CSS styles provided by nbsphinx
and by your Sphinx theme, don’t worry, you can add your own styles easily.
For All Pages#
Just create your own CSS file, e.g. my-own-style.css
, and put it into the _static/
sub-directory of your source directory.
You’ll also have to set the config values html_static_path and html_css_files in your conf.py
, e.g. like this:
html_static_path = ['_static']
html_css_files = ['my-own-style.css']
For All RST files#
If you want your style to only apply to *.rst
files (and not Jupyter notebooks or other source files), you can use rst_prolog with the raw directive in your conf.py
like this:
rst_prolog = """
.. raw:: html
<style>
h1 {
color: fuchsia;
}
</style>
"""
For All Notebooks#
Similarly, if you want your style to only apply to notebooks, you can use nbsphinx_prolog like this:
nbsphinx_prolog = """
.. raw:: html
<style>
h1 {
color: chartreuse;
}
</style>
"""
For a Single Notebook#
For styles that should affect only the current notebook, you can simply insert <style>
tags into Markdown cells like this:
<style>
.nbinput .prompt,
.nboutput .prompt {
display: none;
}
</style>
This CSS example removes the input and output prompts from code cells, see the following cell:
[1]:
6 * 7
[1]:
42
Normal reStructuredText Files#
This is a normal RST file.
Note
Those still work!
Links to Notebooks (and Other Sphinx Source Files)#
Links to Sphinx source files can be created like normal Sphinx hyperlinks, just using a relative path to the local file: link.
using a relative path to the local file: link_.
.. _link: subdir/a-notebook-in-a-subdir.ipynb
If the link text has a space (or some other strange character) in it, you have to surround it with backticks: a notebook link.
surround it with backticks: `a notebook link`_.
.. _a notebook link: subdir/a-notebook-in-a-subdir.ipynb
You can also use an anonymous hyperlink target, like this: link. If you have multiple of those, their order matters!
like this: link__.
__ subdir/a-notebook-in-a-subdir.ipynb
Finally, you can use Embedded URIs, like this link.
like this `link <subdir/a-notebook-in-a-subdir.ipynb>`_.
Note
These links should also work on Github and in other rendered reStructuredText pages.
Links to subsections are also possible by adding a hash sign (#
) and the
section title to any of the above-mentioned link variants.
You have to replace spaces in the section titles by hyphens.
For example, see this subsection.
For example, see this subsection_.
.. _subsection: subdir/a-notebook-in-a-subdir.ipynb#A-Sub-Section
Links to Notebooks, Ye Olde Way#
In addition to the way shown above, you can also create links to notebooks (and other Sphinx source files) with :ref:. This has some disadvantages:
It is arguably a bit more clunky.
Because
:ref:
is a Sphinx feature, the links don’t work on Github and other rendered reStructuredText pages that use plain olddocutils
.
It also has one important advantage:
The link text can automatically be taken from the actual section title.
A link with automatic title looks like this: Notebooks in Sub-Directories.
:ref:`/subdir/a-notebook-in-a-subdir.ipynb`
But you can also provide your own link title.
:ref:`your own link title </subdir/a-notebook-in-a-subdir.ipynb>`
However, if you want to use your own title, you are probably better off using the method described above in Links to Notebooks (and Other Sphinx Source Files).
Links to subsections are also possible, e.g. A Sub-Section (the subsection title is used as link text) and alternative text.
These links were created with:
:ref:`/subdir/a-notebook-in-a-subdir.ipynb#A-Sub-Section`
:ref:`alternative text </subdir/a-notebook-in-a-subdir.ipynb#A-Sub-Section>`
Note
The paths have to be relative to the top source directory and they have to start with a slash (
/
).Spaces in the section title have to be replaced by hyphens!
Sphinx Directives for Info/Warning Boxes#
Warning
This is an experimental feature! Its usage may change in the future or it might disappear completely, so don’t use it for now.
With a bit of luck, it will be possible (some time in the future) to create
info/warning boxes in Markdown cells, see
https://github.com/jupyter/notebook/issues/1292.
If this ever happens, nbsphinx
will provide directives for creating such
boxes.
For now, there are two directives available: nbinfo
and nbwarning
.
This is how an info box looks like:
Note
This is an info box.
It may include nested formatting, even another info/warning box:
Warning: You should probably not use nested boxes!
Domain Objects#
References#
There are different ways of handling references, for example you could use the standard Sphinx citations, but it might be more practical to use the sphinxcontrib.bibtex extension.
After installing the sphinxcontrib.bibtex extension, you have to enable it in
your conf.py
and select the BibTeX file(s) you want to use:
extensions = [
'nbsphinx',
'sphinxcontrib.bibtex',
# Probably more extensions here ...
]
bibtex_bibfiles = ['my-references.bib']
bibtex_reference_style = 'author_year'
Afterwards all the references defined in the bibliography file(s) can be used throughout the Jupyter notebooks and other source files as detailed in the following.
Citations#
You can create citations like [Pérez et al., 2011]:
:cite:`perez2011python`
You can also create so-called in-text citations, where the names of the authors, for example Pérez et al. [2011], are part of the sentence:
:cite:t:`perez2011python`
You can create similar citations in Jupyter notebooks with a special HTML syntax, see the section about citations in Markdown cells.
You can create a list of references in any reStructuredText file (or reST cell in a notebook) like this:
.. bibliography::
For an example, see the file doc/references.rst
.
Footnote citations#
With a sphinxcontrib.bibtex version of >= 2.0.0
it is
possible to create footnote bibliographies with footnote
citations like [1].
:footcite:`perez2011python`
In-text citations like Kluyver et al.[2] can be created like this:
:footcite:t:`kluyver2016jupyter`
Also footnote citations can be used within Jupyter notebooks with a special HTML syntax, see the section about footnote citations in Markdown cells. Footnote citations are restricted to their own source file and the assembly of the bibliography is (analogously to normal citations) invoked with the
.. footbibliography::
directive. For example, a footnote bibliography might look like this (in HTML output):
Fernando Pérez, Brian E. Granger, and John D. Hunter. Python: an ecosystem for scientific computing. Computing in Science Engineering, 13(2):13–21, 2011. doi:10.1109/MCSE.2010.119.
Thomas Kluyver, Benjamin Ragan-Kelley, Fernando Pérez, Brian Granger, Matthias Bussonnier, Jonathan Frederic, Kyle Kelley, Jessica Hamrick, Jason Grout, Sylvain Corlay, Paul Ivanov, Damián Avila, Safia Abdalla, Carol Willing, and Jupyter Development Team. Jupyter Notebooks—a publishing format for reproducible computational workflows. In Fernando Loizides and Birgit Schmidt, editors, Positioning and Power in Academic Publishing: Players, Agents and Agendas, pages 87–90. IOS Press, 2016. doi:10.3233/978-1-61499-649-1-87.
In the LaTeX/PDF output, there is no list of references appearing right here. Instead, the footnote citations are placed into the footnotes of their respective pages.
Thumbnail Link Galleries (HTML only)#
In some case it is desired to create thumbnail links to existing notebooks,
already included in a toctree
. This can be used e.g. to link to a subset
of notebooks from API documentation to highlight the use of some functionality.
For this there is a dedicated nblinkgallery
directive.
The following example gallery was created using:
.. nblinkgallery::
:caption: A few links
:name: rst-link-gallery
gallery/multiple-outputs
gallery/no-thumbnail
gallery/cell-metadata
orphan
A few links
See also
Thumbnail Galleries#
With nbsphinx
you can create thumbnail galleries in notebook files
as described in Gallery With Nested Documents.
If you like, you can also create such galleries in reST files
using the nbgallery
directive.
It takes the same parameters as the toctree directive.
Note
The notes regarding LaTeX in Gallery With Nested Documents and Using toctree In A Notebook also apply here!
The following example gallery was created using:
.. nbgallery::
:caption: This is a thumbnail gallery:
:name: rst-gallery
:glob:
:reversed:
gallery/*-rst
Dummy Notebook 1 for Gallery#
This is a dummy file just to fill the gallery in the reST file.
The thumbnail image is assigned in conf.py.
Dummy Notebook 2 for Gallery#
This is a dummy file just to fill the gallery in the reST file.
The thumbnail image is assigned in conf.py.
The source file is, for no particular reason, a Python script adhering to the py:percent
format. It is parsed with the help of Jupytext, see Custom Notebook Formats.
[1]:
from pathlib import Path
[2]:
filename = 'due-rst.pct.py'
print(Path(filename).read_text())
# %% [markdown]
# # Dummy Notebook 2 for Gallery
#
# This is a dummy file just to fill
# [the gallery in the reST file](../a-normal-rst-file.rst#thumbnail-galleries).
#
# The thumbnail image is assigned in [conf.py](../conf.py).
# %% [markdown]
# The source file is, for no particular reason,
# a Python script adhering to the `py:percent` format.
# It is parsed with the help of [Jupytext](https://jupytext.readthedocs.io/),
# see [Custom Notebook Formats](../custom-formats.ipynb).
# %%
from pathlib import Path
# %%
filename = 'due-rst.pct.py'
print(Path(filename).read_text())
Using Markdown Files#
Sphinx on its own doesn’t know how to handle Markdown files, but there are extensions that enable their usage as Sphinx source files. For an example, see the Sphinx documentation.
Alternatively, when using nbsphinx
it is also possible to use Markdown files via custom notebook formats.
You only need to install the jupytext package and add a configuration setting to conf.py
, which can be used to select one of several Markdown flavors supported by jupytext (here we are using R Markdown):
nbsphinx_custom_formats = {
'.md': ['jupytext.reads', {'fmt': 'Rmd'}],
}
This very page was generated from a Markdown file using these settings.
Links to Notebooks (and Other Sphinx Source Files)#
Links to other Sphinx source files can be created like in Markdown cells of notebooks.
Math#
Mathematical equations can be used just like in Markdown cells of notebooks.
Inline like this: \(\text{e}^{i\pi} = -1\).
Or as a separate block:
\begin{equation*} \int\limits_{-\infty}^\infty f(x) \delta(x - x_0) dx = f(x_0) \end{equation*}
Tables#
A |
B |
A and B |
---|---|---|
False |
False |
False |
True |
False |
False |
False |
True |
False |
True |
True |
True |
Images#
External Links#
nbconvert
The official conversion tool of the Jupyter project. It can be used to convert notebooks to HTML, LaTeX and many other formats.
Its --execute
flag can be used to automatically execute notebooks before conversion.
https://nbconvert.readthedocs.io/
https://github.com/jupyter/nbconvert
RunNotebook (notebook_sphinxext.py)
Notebooks can be included in *.rst
files with a custom notebook
directive. Uses nbconvert
to execute notebooks and to convert the result to HTML.
No LaTeX support.
https://github.com/ngoldbaum/RunNotebook
There are some forks:
https://bitbucket.org/yt_analysis/yt-doc/src/default/extensions/notebook_sphinxext.py
(not available anymore)https://github.com/matthew-brett/perrin-academy/blob/master/sphinxext/notebook_sphinxext.py
nbsite
Build a tested, sphinx-based website from notebooks.
ipypublish
A workflow for creating and editing publication ready scientific reports and presentations, from one or more Jupyter Notebooks, without leaving the browser!
https://ipypublish.readthedocs.io/
https://github.com/chrisjsewell/ipypublish
jupyterbook
Jupyter Book is an open source project for building beautiful, publication-quality books and documents from computational material.
https://github.com/executablebooks/jupyter-book
MyST-NB
A collection of tools for working with Jupyter Notebooks in Sphinx.
The primary tool this package provides is a Sphinx parser for ipynb
files. This allows you to directly convert Jupyter Notebooks into Sphinx documents. It relies heavily on the MyST parser.
https://myst-nb.readthedocs.io/
https://github.com/executablebooks/MyST-NB
notebook-to-pdf
This Jupyter notebook extension allows you to save your notebook as a PDF.
Three new features compared to the official “save as PDF” extension:
produce a PDF with the smallest number of page breaks,
the original notebook is attached to the PDF; and
this extension does not require LaTex.
https://github.com/betatim/notebook-as-pdf
nbinteract
Create interactive webpages from Jupyter Notebooks
https://github.com/SamLau95/nbinteract
nb_pdf_template
An extended nbconvert
template for LaTeX output.
https://github.com/t-makaro/nb_pdf_template
nb2plots
Notebook to reStructuredText converter which uses a modified version of the matplotlib plot
directive.
https://github.com/matthew-brett/nb2plots
brole
A Sphinx role for IPython notebooks
https://github.com/matthew-brett/brole
Sphinx-Gallery
https://sphinx-gallery.readthedocs.io/
sphinx-nbexamples
https://sphinx-nbexamples.readthedocs.io/
https://github.com/Chilipp/sphinx-nbexamples
nbsphinx-link
https://github.com/vidartf/nbsphinx-link
Uses nbsphinx
, but supports notebooks outside the Sphinx source directory.
See https://github.com/spatialaudio/nbsphinx/pull/33 for some limitations.
bookbook
Uses nbconvert
to create a sequence of HTML or a concatenated LaTeX file from a sequence of notebooks.
https://github.com/takluyver/bookbook
jupyter-sphinx
Jupyter Sphinx is a Sphinx extension that executes embedded code in a Jupyter kernel, and embeds outputs of that code in the output document. It has support for rich output such as images, Latex math and even javascript widgets.
https://jupyter-sphinx.readthedocs.io/
https://github.com/jupyter/jupyter-sphinx
DocOnce
http://hplgit.github.io/doconce/doc/web/index.html
Quarto
Open-source scientific and technical publishing system built on Pandoc.
https://github.com/quarto-dev/quarto-cli
Converting Notebooks to reStructuredText
https://github.com/perrette/dimarray/blob/master/docs/scripts/nbconvert_to_rst.py
https://gist.github.com/hadim/16e29b5848672e2e497c
(not available anymore)
https://sphinx-ipynb.readthedocs.io/
Converting reStructuredText to Notebooks
https://github.com/nthiery/rst-to-ipynb
https://github.com/QuantEcon/sphinxcontrib-jupyter
Converting Notebooks to HTML for Blog Posts
http://dongweiming.github.io/divingintoipynb_nikola/posts/nbconvert.html
https://github.com/getpelican/pelican-plugins/blob/master/liquid_tags/notebook.py
Further Posts and Issues
https://github.com/ipython/ipython/issues/4936
https://mail.scipy.org/pipermail/ipython-user/2013-December/013490.html
(not available anymore)
Contributing#
If you find bugs, errors, omissions or other things that need improvement, please create an issue or a pull request at https://github.com/spatialaudio/nbsphinx/. Contributions are always welcome!
Development Installation#
Make sure that the necessary prerequisites are installed.
Then, instead of pip
-installing the latest release from PyPI,
you should get the newest development version (a.k.a. “master”) with Git:
git clone https://github.com/spatialaudio/nbsphinx.git
cd nbsphinx
python3 -m pip install -e .
… where -e
stands for --editable
.
When installing this way, you can quickly try other Git branches (in this example the branch is called “another-branch”):
git checkout another-branch
If you want to go back to the “master” branch, use:
git checkout master
To get the latest changes from Github, use:
git pull --ff-only
Building the Documentation#
If you make changes to the documentation, you should create the HTML pages locally using Sphinx and check if they look OK.
Initially, you might need to install a few packages that are needed to build the documentation:
python3 -m pip install -r doc/requirements.txt
To (re-)build the HTML files, use:
python3 setup.py build_sphinx
If you want to check the LaTeX output, use:
python3 setup.py build_sphinx -b latex
Again, you’ll probably have to use python
instead of python3
.
The generated files will be available in the directories build/sphinx/html/
and build/sphinx/latex/
, respectively.
Building Themes#
The nbsphinx
documentation is available in over 30 different HTML themes,
with each having its own branch ending in -theme
.
To simplify the building and testing of themes,
which is especially needed when changing CSS,
we provide you with command line tool to build all themes
or a user specified subset.
The tool is located at theme_comparison.py
and can be run with:
python3 theme_comparison.py
Before doing that, the required dependencies can be obtained with:
python3 theme_comparison.py --requirements
This will create a list of dependencies in
theme_comparison/theme_requirements.txt
.
The dependencies can then be installed with:
python3 -m pip install -r theme_comparison/theme_requirements.txt
If you just want to build a subset of the themes
(e.g. alabaster
and sphinx_rtd_theme
), simply run:
python3 theme_comparison.py alabaster rtd
For more information run:
python3 theme_comparison.py --help
Testing#
Unfortunately, the currently available automated tests are very limited. Contributions to improve the testing situation are of course also welcome!
The nbsphinx
documentation also serves as a test case.
However, the resulting HTML/LaTeX/PDF files have to be inspected manually to
check whether they look as expected.
Sphinx’s warnings can help spot problems, therefore it is recommended to use the
-W
flag to turn Sphinx warnings into errors while testing:
python3 setup.py build_sphinx -W
This flag is also used for continuous integration on Github Actions
(see the files .github/workflows/*.yml
) and
CircleCI (see the file .circleci/config.yml
).
Sphinx has a linkcheck
builder that can check whether all URLs used in the
documentation are still valid.
This is also part of the continuous integration setup on CircelCI.
References#
By default, in the LaTeX/PDF output the list of references will not appear here, but instead at the end of the document. For a possible work-around (which is also used here) see https://github.com/mcmtroffaes/sphinxcontrib-bibtex/issues/156.
The list of references may look something like this:
Thomas Kluyver, Benjamin Ragan-Kelley, Fernando Pérez, Brian Granger, Matthias Bussonnier, Jonathan Frederic, Kyle Kelley, Jessica Hamrick, Jason Grout, Sylvain Corlay, Paul Ivanov, Damián Avila, Safia Abdalla, Carol Willing, and Jupyter Development Team. Jupyter Notebooks—a publishing format for reproducible computational workflows. In Fernando Loizides and Birgit Schmidt, editors, Positioning and Power in Academic Publishing: Players, Agents and Agendas, pages 87–90. IOS Press, 2016. doi:10.3233/978-1-61499-649-1-87.
Fernando Pérez, Brian E. Granger, and John D. Hunter. Python: an ecosystem for scientific computing. Computing in Science Engineering, 13(2):13–21, 2011. doi:10.1109/MCSE.2010.119.
Warning
With docutils
versions 0.18 and 0.19,
the HTML output after the bibliography is broken,
see https://github.com/mcmtroffaes/sphinxcontrib-bibtex/issues/309.
This problem has been fixed in docutils
version 0.20.
Version History#
- Version 0.9.4 – 2024-05-06 – PyPI – diff
Require
docutils >= 0.18.1
Minor fixes, documentation and CI updates
- Version 0.9.2 – 2023-05-24 – PyPI – diff
Improve support for
sphinx_immaterial
themeImprove support for links starting with
#
Add support for in-text citations
LaTeX: Add support for admonition titles
- Version 0.9.0 – 2023-03-12 – PyPI – diff
Split
nbsphinx.py
(a Python module) into:nbsphinx/__init__.py
(a Python package)A standalone CSS file
nbsphinx-code-cells.css_t
LaTeX style file
nbsphinx.sty
Add custom HTML/CSS for thumbnail galleries
Separate CSS file
nbsphinx-gallery.css
The CSS from Sphinx Gallery (
'sphinx_gallery.load_style'
) cannot be used anymore
Use the last image in a notebook as the default thumbnail
- Version 0.8.8 – 2021-12-31 – PyPI – diff
Support for the
sphinx_codeautolink
extensionBasic support for the
text
builder
- Version 0.8.5 – 2021-05-12 – PyPI – diff
Freeze Jinja2 version to 2.11 (for now, until a bugfix is found)
Add
theme_comparison.py
tool for creating multiple versions (with different HTML themes) of the docs at once
- Version 0.8.4 – 2021-04-29 – PyPI – diff
Support for
mathjax3_config
(for Sphinx >= 4)Force loading MathJax on HTML pages generated from notebooks (can be disabled with
nbsphinx_assume_equations = False
)
- Version 0.8.2 – 2021-02-28 – PyPI – diff
Add support for
data-footcite
HTML attributeDisable automatic highlighting in notebooks, setting
highlight_language
is no longer needed
- Version 0.8.0 – 2020-10-20 – PyPI – diff
Don’t overwrite Pygments background in notebook code cells. To get rid of those ugly greenish code blocks, remove
pygments_style = 'sphinx'
from yourconf.py
.Switch documentation to insipid theme by default
Require Python 3.6+
- Version 0.7.0 – 2020-05-08 – PyPI – diff
Warnings can be suppressed with
suppress_warnings
.<img>
tags are handled in Markdown cells; thealt
,width
,height
andclass
attributes are supported.CSS: prompts protrude into left margin if
nbsphinx_prompt_width
is too small. If you want to hide the prompts, use custom CSS.
- Version 0.6.1 – 2020-04-18 – PyPI – diff
.ipynb_checkpoints
is automatically added toexclude_patterns
- Version 0.6.0 – 2020-04-03 – PyPI – diff
Thumbnail galleries (inspired by https://sphinx-gallery.github.io/)
nbsphinx-toctree
as cell tagKeyword arguments in
nbsphinx_custom_formats
Python 2 support has been dropped
- Version 0.5.1 – 2020-01-28 – PyPI – diff
This will be the last release supporting Python 2.x!
Support for https://github.com/choldgraf/sphinx-copybutton
Executed notebooks are now saved in the HTML output directory
- Version 0.5.0 – 2019-11-20 – PyPI – diff
Automatic support for Jupyter widgets, customizable with
nbsphinx_widgets_path
(andnbsphinx_widgets_options
)
- Version 0.4.3 – 2019-09-30 – PyPI – diff
Add option
nbsphinx_requirejs_path
(andnbsphinx_requirejs_options
)
- Version 0.4.2 – 2019-01-15 – PyPI – diff
Re-establish Python 2 compatibility (but the clock is ticking …)
- Version 0.4.0 – 2018-12-14 – PyPI – diff
Support for “data-cite” HTML tags in Markdown cells
Add option
nbsphinx_custom_formats
LaTeX macros
\nbsphinxstartnotebook
and\nbsphinxstopnotebook
Support for cell attachments
Add options
nbsphinx_input_prompt
andnbsphinx_output_prompt
Re-design LaTeX output of code cells, fix image sizes
- Version 0.3.5 – 2018-09-10 – PyPI – diff
Disable
nbconvert
version 5.4 to avoid issue #878
- Version 0.3.3 – 2018-04-25 – PyPI – diff
Locally linked files are only copied for Jupyter notebooks (and not anymore for other Sphinx source files)
- Version 0.3.2 – 2018-03-28 – PyPI – diff
Links to local files are rewritten for all Sphinx source files (not only Jupyter notebooks)
- Version 0.3.1 – 2018-01-17 – PyPI – diff
Enable notebook translations (NB: The use of reST strings is temporary!)
- Version 0.3.0 – 2018-01-02 – PyPI – diff
Add options
nbsphinx_prolog
andnbsphinx_epilog
Links from
*.rst
files to notebooks have to start with a slash
- Version 0.2.12 – 2016-12-19 – PyPI – diff
Basic support for widgets
CSS is now “responsive”, some new CSS classes
- Version 0.2.8 – 2016-05-20 – PyPI – diff
Add options
nbsphinx_execute
andnbsphinx_execute_arguments
Separate “display priority” for HTML and LaTeX
- Version 0.2.7 – 2016-05-04 – PyPI – diff
Special CSS tuning for
sphinx_rtd_theme
Replace info/warning
<div>
elements withnbinfo
/nbwarning
- Version 0.2.6 – 2016-04-12 – PyPI – diff
Support for LaTeX math environments in Markdown cells
Add options
nbsphinx_timeout
andnbsphinx_codecell_lexer
- Version 0.2.5 – 2016-03-15 – PyPI – diff
Add option
nbsphinx_allow_errors
to globally ignore exceptionsSeparate class nbsphinx.Exporter
- Version 0.2.1 – 2016-01-04 – PyPI – diff
No need to mention
source_suffix
andsource_parsers
inconf.py
- Version 0.2.0 – 2015-12-27 – PyPI – diff
Add support for
allow_errors
andhidden
metadataAdd custom reST template
Add nbinput and nboutput directives with HTML+CSS and LaTeX formatting
Turn nbsphinx into a Sphinx extension
- Version 0.1.0 – 2015-11-29
Initial release
There is also An Orphan Notebook (HTML Only), just for the sake of it.
How To Navigate This Site
Use the next and previous links at the top and the bottom of each page to flip through the pages. Alternatively, you can use the right and left arrow keys on your keyboard. Some additional keyboard shortcuts are provided via the accesskey feature: n next, p previous, u up (= to the parent page), i index, s search and m menu (= open/close sidebar).
Click on the hamburger button in the topbar to open and close the sidebar. The width of the sidebar can be adjusted by dragging its border. Click on the title in the topbar to scroll to the top of the page, if already at the top, go “up” to the parent page (eventually ending up on this very page).
On touch-enabled devices: Tap at the top of the page to show the topbar (if it was scrolled away); swipe from the left edge to show the sidebar, swipe towards the left to hide it.