Zijun Zhang Bioinformatics Researcher @ Simons Foundation

Host a ReadTheDocs site for your package in 7 Steps by Sphinx


So today I decided to give it another try for documentation genration for my new package Darts. I previously tried Sphinx for CLAM, but that didn’t work out well. Since I am now a bit smarter to have successfully compiled a pypi and Anaconda packages, I think maybe it’s time to write down my experience for Sphinx, so that next time I could simply follow the dummie’s guide for Python documentation site generation, and hopefully help others save some time.

the Great Sphinx of Giza, Egypt

The Great Sphinx of Giza, Egypt.

1. Preparation works

First install Sphinx. There are different ways to this, but let’s go with the mighty conda:

$ conda install sphinx

Now in the github repo, checkout a new branch “doc” so that we don’t mess up with other devs.

Make a new folder named “docs” - this is where the documents will reside, and is consistent with Github page’s requirements.

git checkout -B doc
mkdir docs

2. Initialize a skeleton for Sphinx doc.

This involves a few different options - I would like to separate the source and build directories, enable autodoc, and have view source code linked.

cd docs/

I am building the doc for Darts_BHT for this example.

So now we can look at the initial product by

make html
firefox build/html/index.html

Firefox should pop-up and show the almost blank index page: 1.png

3. Adding an API/module page

Currently the doc site does not contain anything. Let’s add the docstring from Python scripts to the doc, by using the sphinx-apidoc utility. In fact, it has become a fairly common practice to write comprehensive docstrings within the python code, to increase readability. For me, it helps a lot to review code that I wrote a few years ago, so is a good habit to keep.

sphinx-apidoc -o source/ ../Darts_BHT

If you have trouble in this step, make sure your package is importable by first running

python setup.py develop
python -c "import Darts_BHT"

This will install the package in a virtual env. To test the installation is ok, use the “python -c” line to import it.

Change “Darts_BHT” to your package name. You should have the modules.rst file generated. Include this .rst file in the index by changing index.rst to

.. toctree::
   :maxdepth: 2
   :caption: Contents:


Now generate the html again by

make html
firefox build/html/index.html

You can see the API doc has now been added to the “Table of Contents”:


You can change the level of depth to display by changing the “:maxdepth: N” line in the above index.rst file.

4. Changing HTML theme and Google-style docstring.

Next we can change a few things in the source/conf.py to customize the doc site. For example, we shall first change the style from the default “alabaster” to “sphinx_rtd_theme” (i.e. ReadTheDocs theme).


You might have to install the theme manually:

pip install sphinx_rtd_theme

Before you enjoy the new good-looking rtd theme, add another few lines to conf.py so that the google-style docstring is properly recognized:

extensions = [
napoleon_google_docstring = True
napoleon_use_param = True
napoleon_use_ivar = True

Now the new doc site should look like this - time to actually write your docstrings! OK I admit I left most docstrings as “TODO” in the initial development..


5. Writting the docstring.

I guess there are a lot to write about the docstrings, but one good example is worth one thousand words! I’ve been using this source as a reference to write docstrings:


It takes time to write good docstrings, but think about the process from one year later, and you would thank yourself for writing the details in the implementation at this time!

6. Add “README.md”, “Get Started” to the doc site

A lot of times we also wrote an informative README file on the Github repo, so that people get to know what this project does at the first glance. We can incorporate that information within our doc site - and to reduce the amount of work and keep things in consistency, we can just use include to do the work.

Specifically, write the following content to source/read.rst:

.. include:: ../../README.rst

If your README is in Markdown format, like I do, you will need another package m2r by pip install m2r. First, change the above .. include:: to .. mdinclude:: ../../README.md

And also add the m2r extension within the source/conf.py, just like how we added the Google-style docstring napoleon extension in step #4:

extensions = [

If you still encounters issues, see the m2r github page for help: https://github.com/miyakogi/m2r#sphinx-integration.

If your package is mostly about API, running the sphinx-apidoc will mostly do the trick.

On the other hand, it’s always good to have a minimal set of examples to get people started quickly. You can do this the same way as writing a “README.md”, then either include that in the index.rst file by adding that to the toc, or use .. mdinclude:: to directly render it within the index page.

Till now, the doc site should look pretty close to the standards:


7. Connect to ReadTheDocs for hosting the doc site

Now the final step, host your site on ReadTheDocs. If you haven’t already, you should register an account there. It provides direct integration with GitHub, but I prefer to use a standalone account.

There are a few quick things to modify in the Github repo before importing it to ReadTheDocs:

  • Add a readthedocs.yaml file. In my case I just used the template below and it simply went through. For more details, see here.
  • Modify setup.py to include the package m2r and other custom Sphinx extensions used, to the “install_requires” options.
# .readthedocs.yml
version: 2
  version: 2.7
     - method: pip
       path: .

Next, you can import a GitHub repo manually by just providing a Git link. In about 1 minute, your site should be up and running with a domain name “package_name.readthedocs.io”, like the one I have here http://darts-bht.readthedocs.io/ !


  1. I’ve encoutered a blog saying why Markdown is not good for Documentations. Not sure if that’s true, but all I know is when Sphinx only supports RST I could not get anything to work!

Similar Posts