The problem

We love Jupyter notebooks for accommodating a computational narrative — a combination of explanation, code, and the output of this code.

Unfortunately, some tasks cannot be accomplished well by notebooks.

If you are writing documentation for your software project, chances are that you want to provide navigation across many tutorials and explanation pages.

You will also want to automatically document the API, perhaps also maintain a bibliography, and you certainly will want all the classes and functions from your module to automatically link to their documentation pages.

In short, your best bet is Sphinx.

Sphinx does not provide a way to build a computational narrative: by itself, it cannot execute any code, nor does it know how to handle the output of that code. This limitation is well known and there are great tools offering a workaround; I’ll list the ones that I know about:

nbsphinx allows incorporating executed notebooks into a documentation website. Unfortunately, markdown used in notebooks is a much more limited markup language than restructured text.

allows incorporating executed notebooks into a documentation website. Unfortunately, markdown used in notebooks is a much more limited markup language than restructured text. sphinx-gallery takes a collection of scripts, executes them, shows the code and the output in the documentation, and even automatically links object names occurring in a script to their documentation. It also parses rst-formatted comments and renders those.

Jupyter-sphinx

We have just made an addition to this list, a freshly rewritten jupyter-sphinx extension, that was previously specialized to render Jupyter widgets.

To embed arbitrary output in your documentation using jupyter-sphinx you only need to use the jupyter-execute directive:

.. jupyter-execute:: print('Hello world!')

Under the hood, all such code chunks are converted to cells in a notebook and executed using nbconvert . We then rely on the Jupyter format and protocol to interpret what to do with the results of executing the code. This means you already know how the output will be shown: we apply exactly the same logic as Jupyter notebook does.

For example, here we make a plot:

And here we are rendering some widgets:

If you want to see jupyter-sphinx used to make package documentation, check out adaptive , the first adopter (full disclosure—I am one of its authors).

An important corollary: building upon the Jupyter kernel protocol makes jupyter-sphinx language-agnostic; jupyter-sphinx works with absolutely any language for which a kernel exists.

Try it