nbsphinx

nbsphinx is a Sphinx extension that provides a source parser for *.ipynb files.

Install

pip install nbsphinx

Then, add the extension to your conf.py:

conf.py
extensions = [
    # ...
    "nbsphinx",
]

Examples

Here are some examples to show how nbsphinx rendering ipynb files.

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.

Math

[6]:
from IPython.display import Math

eq = Math(r"\int\limits_{-\infty}^\infty f(x) \delta(x - x_0) dx = f(x_0)")
eq
[6]:
$\displaystyle \int\limits_{-\infty}^\infty f(x) \delta(x - x_0) dx = f(x_0)$
[7]:
display(eq)
$\displaystyle \int\limits_{-\infty}^\infty f(x) \delta(x - x_0) dx = f(x_0)$
[8]:
from IPython.display import Latex

Latex(r"This is a \LaTeX{} equation: $a^2 + b^2 = c^2$")
[8]:
This is a \LaTeX{} equation: $a^2 + b^2 = c^2$
[9]:
%%latex
\begin{equation}
\int\limits_{-\infty}^\infty f(x) \delta(x - x_0) dx = f(x_0)
\end{equation}
\begin{equation} \int\limits_{-\infty}^\infty f(x) \delta(x - x_0) dx = f(x_0) \end{equation}

matplotlib

[10]:
import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots(figsize=[6, 3])
x = np.linspace(-5, 5, 50)
ax.plot(x, np.sinc(x));
../../_images/extensions_nbsphinx_24_0.png

YouTube Videos

[11]:
from IPython.display import YouTubeVideo

YouTubeVideo("9_OIs49m56E")
[11]:

Tables

[12]:
import pandas as pd

data = [[1, 2], [3, 4]]
pd.DataFrame(data, columns=["Foo", "Bar"])
[12]:
Foo Bar
0 1 2
1 3 4

ANSI Colors

The standard output and standard error streams may contain ANSI escape sequences to change the text and background colors.

[13]:
print("BEWARE: \x1b[1;33;41mugly colors\x1b[m!", file=sys.stderr)
print("AB\x1b[43mCD\x1b[35mEF\x1b[1mGH\x1b[4mIJ\x1b[7mKL\x1b[49mMN\x1b[39mOP\x1b[22mQR\x1b[24mST\x1b[27mUV")
ABCDEFGHIJKLMNOPQRSTUV
BEWARE: ugly colors!
[14]:
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 
[15]:
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
[16]:
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

Hint

This documentation itself is written in .ipynb. To view the source code, click the Edit this page link on the right sidebar.