Docstrings are commonly used to document Python code. Sphinx is a tool allowing to automatically create clear documentation from Python docstrings and complement this information using a markup language similar to Markdown, called reStructuredText. While I got introduced to Sphinx during an internship, I recently used it to easily create documentation for a small project containing Caffe tools and examples. The documentation can be found here and illustrates the capabilities of Sphinx.
The setup described in the following is available on GitHub:
Sphinx Setup on GitHubInstallation
Before installing Sphinx, it might be beneficial to think about the Python version the project is in. While Python 3 might be standard by now, some projects may need to work in Python 2.x as well (or are forced to by dependencies). Sphinx can be installed through pip
or sudo apt-get
:
# For Python 2.x usage: $ sudo apt-get install python-sphinx # Alternative: $ python -m pip install sphinx # To make sure pip corresponds to Python 2.x # For Python 3 usage: $ sudo apt-get install python3-sphinx # Alternative: $ python3 -m pip install sphinx
Additional themes can easily be installed, for example the alabaster
theme:
$ python -m pip install alabaster # or python3 alternatively ...
To verify the intallation, it is easy to check whether the required commands and libraries are installed:
$ sphinx-quickstart --version $ sphinx-apidoc --version $ python # python3 alternatively ... >>> import sphinx
Quickstart
First, a directory docs
is created to hold the documentation. After changing to this directory, sphinx-quickstart
is invoked:
$ sphinx-quickstart
Most of the given default options should be fine. Still, I prefer to separate build and source and enable the autodoc
, todo
and mathjax
extensions. Sphinx created a makefile docs/Makefile
. Using
$ make html
the documentation can be built. The index.html
can be found in docs/build/htmlindex.html
.
Configuration
Configuration is done in docs/source/conf.py
. In order to find the modules created in the root directory, e.g. module/__init__.py
(as done below), the following lines should be uncommented and adapted as follows:
import os import sys sys.path.insert(0, os.path.abspath('../../'))
All available configuration options are also listed here.
Autodoc
The autodoc
extension enables to automatically generate documentation from docstrings. Therefore, a sample module/__init__.py
file may look as follows:
""" A Sphinx example and cheat sheet. Comments ######## .. comment This is a comment! .. code-block:: python .. comment This is a comment! Basic Syntax ############ *italic* **bold** ``verbatim with special characters such as *, also useful for inline code examples`` .. code-block:: python *italic* **bold** ``verbatim with special characters such as *, also useful for inline code examples`` Links and Downloads ################### Hyperlink: `David Stutz <https://davidstutz.de>`_ Download: :download:`__init__.py <../../module/__init__.py>` .. code-block:: python Hyperlink: `David Stutz <https://davidstutz.de>`_ Download: :download:`__init__.py <../../module/__init__.py>` Headings ######## Level 2 ******* Level 3 ======= Level 4 ------- Level 5 ^^^^^^^ Note that level 5 does not impose any styling, but is added to the table of contents on the left. .. code-block:: python Headings ######## Level 2 ******* Level 3 ======= Level 4 ------- Level 5 ^^^^^^^ Lists ##### * Item 1 * Item 2 * Item 3 * Multi- line item 1. Item 1 2. Item 2 3. Item 3 #. Item 4 #. Item 5 .. code-block:: python * Item 1 * Item 2 * Item 3 * Multi- line item 1. Item 1 2. Item 2 3. Item 3 #. Item 4 #. Item 5 Tables ###### Complex variant: +------------+------------+ | Header 1 | Header 2 | +============+============+ | Cell 1.1 | Cell 1.2 | +------------+------------+ | Multi-column | +------------+------------+ | Cell 3.1 | Multi-row | +------------+ | | Cell 4.1 | | +------------+------------+ Another, simpler variant: ======== ======== Header 1 Header 2 ======== ======== Cell 1.1 Cell 1.2 Cell 2.1 Cell 2.2 ======== ======== .. code-block:: python +------------+------------+ | Header 1 | Header 2 | +============+============+ | Cell 1.1 | Cell 1.2 | +------------+------------+ | Multi-column | +------------+------------+ | Cell 3.1 | Multi-row | +------------+ | | Cell 4.1 | | +------------+------------+ ======== ======== Header 1 Header 2 ======== ======== Cell 1.1 Cell 1.2 Cell 2.1 Cell 2.2 ======== ======== Boxes ##### .. seealso:: See also box ... .. todo:: To do box ... .. warning:: Warning box ... Code #### Simple code box:: print('done ...') Line numbers and language option: .. code-block:: python :linenos: print('done ...') Math #### Note that backslashes need to be escaped! If the math isn't rendered directly, refresh using Shift + F5 or Ctrl + Shift + R (in most browsers). Inline: :math:`\\alpha` Block: .. math:: \\sum_{i = 1}^n w_i x_i .. code-block:: latex Inline: :math:`\\alpha` Block: .. math:: \\sum_{i = 1}^n w_i x_i Images and Figures ################## Image: .. image:: ../images/pocoo.png Figure: .. figure:: ../images/pocoo.png :align: center :alt: Pocoo :figclass: align-center Pocoo figure ... .. code-block:: python Image: .. image:: ../images/pocoo.png Figure: .. figure:: ../images/pocoo.png :align: center :alt: Pocoo :figclass: align-center Pocoo figure ... Misc Elements ############# Topic: .. topic:: My Topic My topic text ... Sidebar: .. sidebar:: My Sidebar My sidebar text ... .. code-block:: python .. topic:: My Topic My topic text ... .. sidebar:: My Sidebar My sidebar text ... Citations ######### Citation in text [Stutz2015]_ .. [Stutz2015] D. Stutz. Superpixel Segmentation: An Evaluation. GCPR, 2015. .. code-block:: python Citation in text [Stutz2015]_ .. [Stutz2015] D. Stutz. Superpixel Segmentation: An Evaluation. GCPR, 2015. Footnotes ######### The footnote section needs to be added at the end ... .. code-block:: python Footnote [#f]_ .. comment:: ... .. rubric:: Footnotes .. [#f] Footenote text ... Footnote [#f]_ .. rubric:: Footnotes .. [#f] Footenote text ... """ class AClass: """ Class docstring, with reference to the :mod:`module`, or another class :class:`module.AnotherClass` and its function :func:`module.AnotherClass.foo`. """ class AnotherClass: """ Another class' docstring. """ def foo(arg1, arg2): """ A method's docstring with parameters and return value. Use all the cool Sphinx capabilities in this description, e.g. to give usage examples ... :Example: >>> another_class.foo('', AClass()) :param arg1: first argument :type arg1: string :param arg2: second argument :type arg2: :class:`module.AClass` :return: something :rtype: string :raises: TypeError """ return '' + 1
The above example demonstrates many of the capabilities of reStructuredText — a Markdown-like markup language used by Sphinx. For example, the docstring corresponding to the whole file (i.e. top-most docstring) illustrates how to create headers, lists, tables, links, footnotes, references and much more. For AClass
and AnotherClass
, the file illustrates how to document parameters and add method examples, e.g.:
def foo(arg1, arg2): """ A method's docstring with parameters and return value. Use all the cool Sphinx capabilities in this description, e.g. to give usage examples ... :Example: >>> another_class.foo('', AClass()) :param arg1: first argument :type arg1: string :param arg2: second argument :type arg2: :class:`module.AClass` :return: something :rtype: string :raises: TypeError """ return '' + 1
Details regarding the used keywords (e.g. :param:
, :type:
...) can be found in the Sphinx documentation. These keywords are then rendered as shown in Figure 1 (using the classic
theme).
Figure 1 (click to enlarge): Illustration of the rendered method documentation generated from the docstring shown above.
Now, that there are some docstrings to generate documentation for, the sphinx-apidoc
command can be used as follows (from within the docs
directory):
$ sphinx-apidoc -f -o source/ ../ $ make html
Troubleshooting
Debugging. When getting Python errors on make html
it is always a good idea to force Sphinx to use the correct Python version first. This can be done by editing docs/Makefile
:
SPHINXBUILD = python -c "import sys,sphinx;sys.exit(sphinx.main(sys.argv))" # Or python3 if necessary.
No module named requests.packages
. When running make html
and obtaining an error such as
$ make html sphinx-build -b html -d build/doctrees source build/html Running Sphinx v1.5 Extension error: Could not import extension sphinx.builders.linkcheck (exception: No module named 'requests.packages') make: *** [html] Error 1
It might help to upgrade the corresponding package, e.g. for Python 3:
sudo python3 -m pip install --upgrade requests