Documenting Python Code with Doxygen
Learn how to effectively document your Python code using Doxygen. This step-by-step guide covers setup, best practices, and tips for generating clear, maintainable documentation.
When most people think of Doxygen, they picture C++ or C-style documentation, since it’s often used for projects hosted on GitHub. But did you know that, besides C++ and Java, Doxygen also supports Python? While it’s not as seamless as tools like Sphinx—which were built for the Python ecosystem—Doxygen can be a surprisingly powerful option, especially if you’re already using it in a multi-language project.
In this post, I’ll walk you through how to document your Python code and how to use Doxygen’s special commands.
Why Use Doxygen for Python?
If your project involves multiple languages (like C++, Python, and Java), using one tool to rule them all saves time—and you don’t need to tinker with several different tools. Doxygen handles this use case well and provides a wide range of output options, from browsable HTML and man pages to LaTeX documentation that can be compiled into a PDF.
Step 1: Install Doxygen
You can find Doxygen in your distro’s repo or on the official website.
- On Arch Linux:
1
sudo pacman -S doxygen
- On Ubuntu/Debian:
1
sudo apt install doxygen
- On macOS (with Homebrew):
1
brew install doxygen
- On Windows: Download the installer or the portable version. The latter is great if you just want to experiment with the tool.
Step 2: Prepare Your Code
There are two ways to document your code. Docstrings are the traditional “Python way,” but to use Doxygen’s special commands, you’ll need to use a different syntax or disable the default docstring handling—which I’ll cover later on. Otherwise, your docstrings will be displayed as plain text without formatting or extra features.
What Are ‘Special Commands’?
Special commands influence the documentation processing by providing style hints or notifying Doxygen about actions like inserting an image into a section.
The most important ones:
\param <name> <description>
: documents a function parameter\return <description>
: describes the return value of a function\file <filename>
: documents information about the file\author <name>
: sets the author of the section\version <version>
: version of the module/file/class, etc.\brief <description>
: a short one-liner about the class/function\details <description>
: detailed description, can span multiple lines\bug <description>
: notes important bugs in the source code\copyright <info>
: notes about licenses that apply\throws <error info>
: info about exceptions that may be raised\see <reference>
: links to another function, class, or section\warning <warning>
: creates a red warning box\deprecated <note>
: marks deprecated sections with a gray box and additional details\package <info>
: information about your Python package\var
: documents a variable\date <date>
: sets the date
The full list of commands is available here.
Example Class
Below is a small example class that uses all of the commands mentioned above:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
## @file your_class.py
# @brief This is an example Python module demonstrating Doxygen special commands.
# @author Your Name
# @date 2025-04-01
## @package your_module
# This module provides sample classes and functions to showcase Doxygen documentation in Python.
## Utility function to divide two numbers.
# @param numerator The numerator of the division.
# @param denominator The denominator of the division.
# @return The result of the division.
# @throws ZeroDivisionError if the denominator is zero.
def divide_numbers(numerator, denominator):
if denominator == 0:
raise ZeroDivisionError("Denominator cannot be zero.")
return numerator / denominator
## @class Person
# @brief Represents a simple person object.
class Person:
## @var name
# The name of the person.
## @var email
# The email address of the person.
## Constructor
# @param name The person's name.
# @param email The person's email address.
def __init__(self, name, email):
self.name = name
self.email = email
## Set a new email for the person.
# @param new_email The new email address.
# @warning This does not check if the email is valid!
def set_email(self, new_email):
self.email = new_email
## @class Calculator
# @brief A simple calculator class.
# @deprecated This class is outdated; use the MathEngine class instead.
class Calculator:
## Adds two values.
# @param x First value.
# @param y Second value.
# @return Sum of x and y.
def add(self, x, y):
return x + y
Tip: If you’re coming from Java with Javadoc, you may use the
@
-prefix instead of the backslash (\
) one.
Step 3: Create a Doxygen Configuration File
The Doxyfile
, Doxygen’s configuration file, stores the information about how and which code should be processed, what output formats to generate, and so on. You can create it by running doxygen -g
in your root folder or by using the doxywizard
GUI tool, which we’ll be using.
Fill in the information about your project, and if you want Doxygen to interpret the Python docstrings, set the option PYTHON_DOCSTRING
to NO
under Expert > Project
.
Step 4: Generate the Documentation
Save your Doxyfile, head over to the Run
tab, and press Run doxygen
and then Show HTML output
. You’ll be presented with your documentation.
In the case of the example above, it looks like the following:
Step 5 (Bonus): Create a PDF File
Tick the option Generate LaTeX
under Expert > LaTeX
, save your changes, and run Doxygen again. You now have the choice of installing a TeX distribution like MikTeX or TeX Live. Alternatively, you can zip the LaTeX output folder and upload it to an online service like Overleaf, which will compile the document for you—no need to mess around with TeX packages or errors.