Documenting your Python library, from zero to website
Documentation is quite a project, but your project is already a project, and who wants another project?
We will start with a totally empty project, and go all the way to a website hosted on GitHub pages, built automatically with GitHub actions.
I said we’d do it from scratch, so we will have to make a library. You probably already have a library, so you can easily figure out how to paste your files here, and skip to the next section.
Let’s create a library called
autos. Create a folder for it and two files:
with contents for
from .bike import *
Let’s also add a test
tests/test.py in a separate directory:
Finally, let’s make this a real package by including a
setup.py. You can use a generator, or just steal the default one from packaging.python.org — create
setup.py with contents:
Obviously, edit it as you see fit. Here you will also need a
README.md to serve as the
long_description (and because) it’s good practice:
The final directory structure should look like:
You should now be able to install the library
pip install .
The test script in the
tests directory should produce:
Riding: SR400 on road: 101
Great! On to the documentation.
Let’s start by adding some documentation. If you are using VS Code (which you should be!), you can use the Python Docstring Generator to help you out.
typing declarations to all the method arguments and return values:
Some other common types are:
Go under one of the method signatures and type
”””. It should suggest the documentation string:
Then hit enter to autocomplete the documentation:
Fill in some documentation, for example:
The neat thing here is that editing the
test.py should in any modern IDE (e.g. VS Code) now give you autocomplete suggestions:
Generating the website
You need to install Sphinx:
pip install -U sphinx
If you are on Ubuntu, possibly you will instead want:
sudo apt-get install python3-sphinx
Let’s make a new
sphinx-quickstart to get started:
Choose all the defaults, i.e.
> Separate source and build directories (y/n) [n]:. For project name, I chose
You should now have in the
The Makefile is obviously used to build the project.
conf.py specifies the build, and
index.rst is the entry point for the website.
To make the website, run:
To make different targets, try just
make to list all possible targets. The resulting pages will be in
_build/html. The default page looks like this:
I always like the ReadTheDocs] theme. Go ahead and install it:
pip install sphinx-rtd-theme
Let’s add it to the configuration in
conf.py. Add the import statement, and add the rest:
Now we get:
That looks better! But we don’t yet have our doc strings we wrote in Python appearing.
Autogenerate RST files
Converting doc strings into documentation is done using the
sphinx.ext.autodoc extension as described here. Go ahead and add it to the extensions list in
extensions = [
In order for specific classse to appear in the documentation, there must be an RST file referencing them. An example snippet in a
.rst file might look like this:
.. automodule:: autos.bike
which shows that the
autos.bike class should be documented here. If you’ve never written RST before, note that it is extremely space and indentation sensitive!
Let’s automatically generate them. From inside the
docs directory, run:
sphinx-apidoc -o . ../autos
-o . specifies that the current
docs directory is the output, and the
../autos specifies the source directory. We obtain two new files:
with contents for
autos.rst (note: you may have to view these in raw format!):
modules.rst contains a running list of the modules:
Finally, we need to connect these new files to the original
index.rst. Add a reference to the
Fire up the
make command again:
to obtain the following:
This almost worked. We notice that for the class documentation, we are missing the docstrings for the constructor!
For some brilliant reason, the
__init__ method is skipped by default! Let’s fix that using this trick. Add the following snippet to
conf.py at the bottom:
Rebuild, making sure clean first:
make clean html
and you should find the constructor is now documented:
Hosting your documentation with GitHub
Start by initializing a git repo with
git init . for the folder which has contents:
You should also use a
.gitignore with at least:
Commit the remaining files in the repo, then go on GitHub, create a new repo for this project and push your first commit.
git add .
git commit -m “Initial”
git remote add origin https://github.com/...
git push — set-upstream origin master
Let’s create a new GitHub Actions workflow. They live in a
.github/workflows directory that does not yet exist. Create it:
Give the file the following contents:
Let’s break it down:
on— you can add different triggers here. Here we build the docs on every push to master. You can also do e.g. pull request.
docs job— this is the only job here, which will build the docs.
runs-on: ubuntu-latest— You can choose from a couple differet runners other than
ubuntu-latestas described here.
uses: actions/checkout@v2— very important! Without this, we don’t actually check out our repo!
Install Python— get the latest 3.8 Python — turns out
Build docs— the
make htmlcommand from before. Make sure we do it in the docs directory.
Deploy— deploy the pages in
gh-pagesbranch such that your docs become visible to the world.
Add, commit and push the workflow. You can monitor the progress of the action on your repo page under
Your website should then be available under:
Mine didn’t appear right away. Check your settings on the “Settings” tab under “GitHub pages” — they should automatically have changed to build from the
I had to manually change this from
master and back to get the website to become available. It should then also automatically list the URL here.
You can also check your
gh-pages branch, which should containt your HTML files:
A common problem in the build process is that you used some external library that you installed with
pip install external_library. Now what — should you add it to the build process for the documentation? No — this only adds more dependencies that need to be installed, and it’s probably not relevant for the docs. Instead you can edit in
conf.py the option:
autodoc_mock_imports = [
such that the build process for the docs will proceed even when the library is missing.
Your final docs are now online, and building every time you push to master!
Finally, we can complete this guide by adding a badge to your
README.md that your docs built:
Thanks for reading!