|
| 1 | +Jupyter Sphinx Extension |
| 2 | +======================== |
| 3 | + |
| 4 | +.. toctree:: |
| 5 | + :maxdepth: 2 |
| 6 | + :caption: Contents: |
| 7 | + |
| 8 | +Jupyter Sphinx is a Sphinx extension that executes embedded code in a Jupyter |
| 9 | +kernel, and embeds outputs of that code in the output document. It has support |
| 10 | +for rich output such as images, Latex math and even javascript widgets. |
| 11 | + |
| 12 | +Enabling the extension |
| 13 | +---------------------- |
| 14 | +To enable the extension, add ``jupyter_sphinx.execute`` to your enabled extensions in |
| 15 | +``conf.py``. |
| 16 | + |
| 17 | +Basic Usage |
| 18 | +----------- |
| 19 | + |
| 20 | +You can use the ``jupyter-execute`` directive to embed code into the document:: |
| 21 | + |
| 22 | + .. jupyter-execute:: |
| 23 | + |
| 24 | + name = 'world' |
| 25 | + print('hello ' + name + '!') |
| 26 | + |
| 27 | +The above is rendered as follows: |
| 28 | + |
| 29 | +.. jupyter-execute:: |
| 30 | + |
| 31 | + name = 'world' |
| 32 | + print('hello ' + name + '!') |
| 33 | + |
| 34 | +Note that the code produces *output* (printing the string 'hello world!'), and the output |
| 35 | +is rendered directly after the code snippet. |
| 36 | + |
| 37 | +Because all code cells in a document are run in the same kernel, cells later in the document |
| 38 | +can use variables and functions defined in cells earlier in the document: |
| 39 | + |
| 40 | +.. jupyter-execute:: |
| 41 | + |
| 42 | + a = 1 |
| 43 | + print('first cell: a = {}'.format(a)) |
| 44 | + |
| 45 | +.. jupyter-execute:: |
| 46 | + |
| 47 | + a += 1 |
| 48 | + print('second cell: a = {}'.format(a)) |
| 49 | + |
| 50 | +Because jupyter-sphinx uses the machinery of ``nbconvert``, it is capable of rendering |
| 51 | +much richer output than mere text; plots, for example: |
| 52 | + |
| 53 | +.. jupyter-execute:: |
| 54 | + |
| 55 | + import numpy as np |
| 56 | + from matplotlib import pyplot |
| 57 | + %matplotlib inline |
| 58 | + |
| 59 | + x = np.linspace(0, 2 * np.pi) |
| 60 | + |
| 61 | + pyplot.plot(x, np.sin(x) / x) |
| 62 | + pyplot.plot(x, np.cos(x)) |
| 63 | + pyplot.grid() |
| 64 | + |
| 65 | +or even full-blown javascript widgets: |
| 66 | + |
| 67 | +.. jupyter-execute:: |
| 68 | + |
| 69 | + import ipywidgets as w |
| 70 | + from IPython.display import display |
| 71 | + |
| 72 | + a = w.IntSlider() |
| 73 | + b = w.IntText() |
| 74 | + display(a, b) |
| 75 | + w.jslink((a, 'value'), (b, 'value')) |
| 76 | + |
| 77 | + |
| 78 | +Directive options |
| 79 | +----------------- |
| 80 | +You may choose to hide the code of a cell, but keep its output visible using ``:hide-code:``:: |
| 81 | + |
| 82 | + .. jupyter-execute:: |
| 83 | + :hide-code: |
| 84 | + |
| 85 | + print('this code is invisible') |
| 86 | + |
| 87 | +produces: |
| 88 | + |
| 89 | +.. jupyter-execute:: |
| 90 | + :hide-code: |
| 91 | + |
| 92 | + print('this code is invisible') |
| 93 | + |
| 94 | +or vice versa with ``:hide-output:``:: |
| 95 | + |
| 96 | + .. jupyter-execute:: |
| 97 | + :hide-output: |
| 98 | + |
| 99 | + print('this output is invisible') |
| 100 | + |
| 101 | +produces: |
| 102 | + |
| 103 | +.. jupyter-execute:: |
| 104 | + :hide-output: |
| 105 | + |
| 106 | + print('this output is invisible') |
| 107 | + |
| 108 | +You may also display the code *below* the output with ``:code-below:``:: |
| 109 | + |
| 110 | + .. jupyter-execute:: |
| 111 | + :code-below: |
| 112 | + |
| 113 | + print('this output is above the code') |
| 114 | + |
| 115 | +produces: |
| 116 | + |
| 117 | +.. jupyter-execute:: |
| 118 | + :code-below: |
| 119 | + |
| 120 | + print('this code is below the output') |
| 121 | + |
| 122 | + |
| 123 | +Controlling exceptions |
| 124 | +---------------------- |
| 125 | + |
| 126 | +The default behaviour when jupyter-sphinx encounters an error in the embedded code is just to |
| 127 | +stop execution of the document and display a stack trace. However, there are many cases where it may be |
| 128 | +illustrative for execution to continue and for a stack trace to be shown as *output of the cell*. This |
| 129 | +behaviour can be enabled by using the ``raises`` option:: |
| 130 | + |
| 131 | + .. jupyter-execute:: |
| 132 | + :raises: |
| 133 | + |
| 134 | + 1 / 0 |
| 135 | + |
| 136 | +produces: |
| 137 | + |
| 138 | +.. jupyter-execute:: |
| 139 | + :raises: |
| 140 | + |
| 141 | + 1 / 0 |
| 142 | + |
| 143 | +Note that when given no arguments, ``raises`` will catch all errors. It is also possible to give ``raises`` |
| 144 | +a list of error types; if an error is raised that is not in the list then execution stops as usual:: |
| 145 | + |
| 146 | + .. jupyter-execute:: |
| 147 | + :raises: KeyError, ValueError |
| 148 | + |
| 149 | + a = {'hello': 'world!'} |
| 150 | + a['jello'] |
| 151 | + |
| 152 | +produces: |
| 153 | + |
| 154 | +.. jupyter-execute:: |
| 155 | + :raises: KeyError, ValueError |
| 156 | + |
| 157 | + a = {'hello': 'world!'} |
| 158 | + a['jello'] |
| 159 | + |
| 160 | + |
| 161 | +Controlling the execution environment |
| 162 | +------------------------------------- |
| 163 | +The execution environment can be controlled by using the ``jupyter-kernel`` directive. This directive takes |
| 164 | +the name of the Jupyter kernel in which all future cells (until the next ``jupyter-kernel`` directive) should |
| 165 | +be run:: |
| 166 | + |
| 167 | + .. jupyter-kernel:: python3 |
| 168 | + :id: a_unique_name |
| 169 | + |
| 170 | +``jupyter-kernel`` can also take a directive option ``:id:`` that names the Jupyter session; |
| 171 | +it is used in conjunction with the ``jupyter-download`` roles described in the next section. |
| 172 | + |
| 173 | +Note that putting a ``jupyter-kernel`` directive starts a *new* kernel, so any variables and functions declared |
| 174 | +in cells *before* a ``jupyter-kernel`` directive will not be available in future cells. |
| 175 | + |
| 176 | +Note that we are also not limited to working with Python: Jupyter Sphinx supports kernels for |
| 177 | +any programming language, and we even get proper syntax highlighting thanks to the power of |
| 178 | +Pygments. |
| 179 | + |
| 180 | +Downloading the code as a script |
| 181 | +-------------------------------- |
| 182 | +Jupyter Sphinx includes 2 roles that can be used to download the code embedded in a document: |
| 183 | +``:jupyter-download:script:`` (for a raw script file) and ``:jupyter-download:notebook:`` (for |
| 184 | +a Jupyter notebook). For example, to download all the code from this document as a script we |
| 185 | +would use:: |
| 186 | + |
| 187 | + :jupyter-download:script:`index` |
| 188 | + |
| 189 | +Which produces a link like this: :jupyter-download:script:`index`. The name that the role is |
| 190 | +applied to (``index`` in this case) is the name of the document for which you wish to download |
| 191 | +the code. If a document contains ``jupyter-kernel`` directives with ``:id:`` specified, then |
| 192 | +the name provided to ``:id:`` can be used to get the code for the cells belonging to the |
| 193 | +that Jupyter session. |
| 194 | + |
| 195 | + |
| 196 | +Configuration options |
| 197 | +--------------------- |
| 198 | + |
| 199 | +Typically you will be using Sphinx to build documentation for a software package. |
| 200 | + |
| 201 | +If you are building documentation for a Python package you should add the following |
| 202 | +lines to your sphinx ``conf.py``:: |
| 203 | + |
| 204 | + import os |
| 205 | + |
| 206 | + package_path = os.path.abspath('../..') |
| 207 | + os.environ['PYTHONPATH'] = ':'.join((package_path, os.environ.get('PYTHONPATH', ''))) |
| 208 | + |
| 209 | +This will ensure that your package is importable by any IPython kernels, as they will |
| 210 | +inherit the environment variables from the main Sphinx process. |
| 211 | + |
| 212 | +Here is a list of all the configuration options available to the Jupyter Sphinx extension: |
| 213 | + |
| 214 | +jupyter_execute_default_kernel |
| 215 | + |
| 216 | + The default kernel to launch when executing code in ``jupyter-execute`` directives. |
| 217 | + The default is ``python3``. |
| 218 | + |
| 219 | + |
| 220 | +jupyter_execute_data_priority |
| 221 | + |
| 222 | + The display priority of different output mimetypes. Mimetypes earlier in the data priority |
| 223 | + list are preferred over later ones. This is relevant if a code cell produces an output |
| 224 | + that has several possible representations (e.g. description text or an image). |
| 225 | + The default is |
| 226 | + ``['application/vnd.jupyter.widget-view+json', 'text/html', 'image/svg+xml', 'image/png', 'image/jpeg', 'text/latex', 'text/plain']``. |
| 227 | + |
| 228 | + |
| 229 | +jupyter_execute_kwargs |
| 230 | + |
| 231 | + Keyword arguments to pass to ``nbconvert.preprocessors.execute.executenb``, which controls how |
| 232 | + code cells are executed. The default is ``dict(timeout=-1, allow_errors=True)``. |
0 commit comments