Good documentation is what transforms a Python package from usable to useful. It helps users get started, understand capabilities, and solve problems. This guide covers modern documentation tools and practices for Python packages.
Documentation Types
Professional documentation includes multiple types:
┌─────────────────────────────────────────────────────────────┐
│ Documentation Quadrant │
├─────────────────────────────────────────────────────────────┤
│ │
│ LEARNING INFORMATION │
│ ────────────────────────────────────────────── │
│ │
│ Tutorials Reference │
│ • Get started quickly • API documentation │
│ • Learning-oriented • Function signatures │
│ • Step-by-step • Complete & accurate │
│ │
│ ────────────────────────────────────────────── │
│ │
│ How-to Guides Explanation │
│ • Solve specific problems • Background & context │
│ • Task-oriented • Why things work │
│ • Practical steps • Architecture decisions │
│ │
│ DOING UNDERSTANDING │
│ │
└─────────────────────────────────────────────────────────────┘
Docstring Formats
Google Style (Recommended)
Clean and readable, works well with type hints:
def process_data(input_path: str, output_path: str, *, validate: bool = True) -> dict:
"""Process data from input file and write to output.
Reads the input file, applies transformations, and writes
the result to the output path.
Args:
input_path: Path to the input file. Must exist.
output_path: Path for the output file. Created if doesn't exist.
validate: Whether to validate data before processing.
Defaults to True.
Returns:
A dictionary containing processing statistics:
- processed: Number of records processed
- errors: Number of errors encountered
- duration: Processing time in seconds
Raises:
FileNotFoundError: If input_path doesn't exist.
ValidationError: If validate=True and data is invalid.
Example:
>>> stats = process_data("input.csv", "output.json")
>>> print(stats["processed"])
100
"""
NumPy Style
Common in scientific Python:
def calculate_statistics(data, axis=None):
"""
Calculate basic statistics for the input data.
Parameters
----------
data : array_like
Input data for statistical calculation.
axis : int or None, optional
Axis along which to compute statistics.
If None, compute over flattened array.
Returns
-------
dict
Dictionary containing:
- mean : float
Arithmetic mean of the data.
- std : float
Standard deviation.
- min : float
Minimum value.
- max : float
Maximum value.
See Also
--------
numpy.mean : Compute arithmetic mean.
numpy.std : Compute standard deviation.
Examples
--------
>>> data = [1, 2, 3, 4, 5]
>>> stats = calculate_statistics(data)
>>> stats['mean']
3.0
"""
Sphinx (reStructuredText) Style
Native Sphinx format:
def fetch_user(user_id, include_details=False):
"""
Fetch a user by ID.
:param user_id: The unique user identifier.
:type user_id: int
:param include_details: Include additional user details.
:type include_details: bool, optional
:returns: User object or None if not found.
:rtype: User or None
:raises ValueError: If user_id is negative.
.. note::
This function makes a network request.
.. warning::
Rate limited to 100 requests per minute.
"""
Sphinx: Full-Featured Documentation
Sphinx is the standard for Python documentation.
Setup
pip install sphinx sphinx-rtd-theme sphinx-autodoc-typehints
# Initialize in your project
cd my-package
sphinx-quickstart docs
# Answer prompts:
# > Separate source and build directories? [n]: n
# > Project name: My Package
# > Author name(s): Your Name
# > Project release: 1.0.0
Project Structure
my-package/
├── src/
│ └── my_package/
│ ├── __init__.py
│ └── core.py
├── docs/
│ ├── conf.py # Sphinx configuration
│ ├── index.rst # Main page
│ ├── installation.rst
│ ├── quickstart.rst
│ ├── api.rst # API reference
│ └── _static/ # Custom CSS, images
├── pyproject.toml
└── README.md
Configuration (conf.py)
# docs/conf.py
import os
import sys
# Add source to path for autodoc
sys.path.insert(0, os.path.abspath("../src"))
# Project information
project = "My Package"
copyright = "2026, Your Name"
author = "Your Name"
release = "1.0.0"
# Extensions
extensions = [
"sphinx.ext.autodoc", # Auto-generate from docstrings
"sphinx.ext.napoleon", # Google/NumPy docstring support
"sphinx.ext.viewcode", # Add links to source code
"sphinx.ext.intersphinx", # Link to other projects
"sphinx_autodoc_typehints", # Type hints in docs
]
# Napoleon settings (for Google/NumPy docstrings)
napoleon_google_docstring = True
napoleon_numpy_docstring = True
napoleon_include_init_with_doc = True
# Autodoc settings
autodoc_default_options = {
"members": True,
"undoc-members": True,
"show-inheritance": True,
}
autodoc_typehints = "description"
# Intersphinx mapping
intersphinx_mapping = {
"python": ("https://docs.python.org/3", None),
"requests": ("https://requests.readthedocs.io/en/latest/", None),
}
# Theme
html_theme = "sphinx_rtd_theme"
html_theme_options = {
"navigation_depth": 4,
}
Main Page (index.rst)
My Package
==========
My Package is a Python library for doing awesome things.
.. toctree::
:maxdepth: 2
:caption: Contents:
installation
quickstart
api
changelog
Features
--------
* Feature one
* Feature two
* Feature three
Quick Example
-------------
.. code-block:: python
from my_package import process
result = process("input.txt")
print(result)
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
API Reference (api.rst)
API Reference
=============
Core Module
-----------
.. automodule:: my_package.core
:members:
:undoc-members:
:show-inheritance:
Utilities
---------
.. automodule:: my_package.utils
:members:
Specific Function
-----------------
.. autofunction:: my_package.process_data
Building Documentation
# Build HTML
cd docs
make html
# View locally
open _build/html/index.html
# Clean build
make clean html
MkDocs: Simple Markdown Docs
MkDocs uses Markdown and is simpler to configure.
Setup
pip install mkdocs mkdocs-material mkdocstrings[python]
# Initialize
mkdocs new .
Project Structure
my-package/
├── src/
│ └── my_package/
├── docs/
│ ├── index.md
│ ├── installation.md
│ ├── quickstart.md
│ ├── api/
│ │ └── core.md
│ └── assets/
├── mkdocs.yml
└── pyproject.toml
Configuration (mkdocs.yml)
# mkdocs.yml
site_name: My Package
site_url: https://mypackage.readthedocs.io/
repo_url: https://github.com/user/my-package
repo_name: user/my-package
theme:
name: material
features:
- navigation.tabs
- navigation.sections
- content.code.copy
palette:
- scheme: default
primary: indigo
accent: indigo
plugins:
- search
- mkdocstrings:
default_handler: python
handlers:
python:
options:
show_source: true
show_root_heading: true
nav:
- Home: index.md
- Getting Started:
- Installation: installation.md
- Quick Start: quickstart.md
- API Reference:
- Core: api/core.md
- Changelog: changelog.md
markdown_extensions:
- pymdownx.highlight:
anchor_linenums: true
- pymdownx.superfences
- admonition
- toc:
permalink: true
API Documentation (api/core.md)
# Core Module
Main functionality of the package.
## process_data
::: my_package.core.process_data
## DataProcessor
::: my_package.core.DataProcessor
options:
members: true
show_source: false
Building
# Serve locally with hot reload
mkdocs serve
# Build static site
mkdocs build
# Deploy to GitHub Pages
mkdocs gh-deploy
Read the Docs
Host your documentation for free with automatic builds.
Configuration (.readthedocs.yaml)
# .readthedocs.yaml
version: 2
build:
os: ubuntu-22.04
tools:
python: "3.11"
# Sphinx
sphinx:
configuration: docs/conf.py
# Or MkDocs
# mkdocs:
# configuration: mkdocs.yml
python:
install:
- method: pip
path: .
extra_requirements:
- docs
pyproject.toml Docs Dependencies
[project.optional-dependencies]
docs = [
"sphinx>=7.0",
"sphinx-rtd-theme>=1.0",
"sphinx-autodoc-typehints>=1.0",
# Or for MkDocs:
# "mkdocs>=1.5",
# "mkdocs-material>=9.0",
# "mkdocstrings[python]>=0.24",
]
Setting Up Read the Docs
- Push your code to GitHub/GitLab/Bitbucket
- Sign up at readthedocs.org
- Import your project
- Configure build settings
- Docs build automatically on each push
Versioned Documentation
Read the Docs builds docs for:
- Main branch (latest)
- Tags (stable versions)
- Feature branches (preview)
# .readthedocs.yaml
version: 2
build:
os: ubuntu-22.04
tools:
python: "3.11"
# Build PDF/EPUB
formats:
- pdf
- epub
Documentation Best Practices
1. Write README First
# My Package
[](https://pypi.org/project/my-package/)
[](https://my-package.readthedocs.io/)
Short description of what your package does.
## Installation
```bash
pip install my-package
Quick Start
from my_package import process
result = process("input.txt")
Documentation
Full documentation: https://my-package.readthedocs.io/
License
MIT
### 2. Include Working Examples
```python
def calculate_sum(numbers: list[int]) -> int:
"""Calculate the sum of numbers.
Example:
>>> calculate_sum([1, 2, 3])
6
>>> calculate_sum([])
0
>>> calculate_sum([-1, 1])
0
Note:
Examples are tested with doctest.
"""
return sum(numbers)
3. Document the Why, Not Just What
def connect(host: str, port: int, timeout: float = 30.0) -> Connection:
"""Connect to the server.
The timeout defaults to 30 seconds, which works well for most
network conditions. For slow connections or when connecting to
remote servers, you may need to increase this value.
If the server uses a non-standard port, ensure your firewall
allows outbound connections on that port.
Args:
host: Server hostname or IP address.
port: Server port number.
timeout: Connection timeout in seconds. Increase for slow
networks or distant servers.
Returns:
Active connection to the server.
"""
4. Use Admonitions
!!! note
This feature requires Python 3.10+
!!! warning
This operation cannot be undone.
!!! tip
Use `--verbose` for detailed output.
!!! danger
Never commit API keys to version control.
.. note::
This feature requires Python 3.10+
.. warning::
This operation cannot be undone.
5. Keep Docs in Sync
# pyproject.toml
[tool.pytest.ini_options]
addopts = "--doctest-modules"
# Run doctests to verify examples
# pytest src/ --doctest-modules
Project Documentation Structure
docs/
├── index.rst/md # Introduction, quick links
├── installation.rst/md # How to install
├── quickstart.rst/md # 5-minute tutorial
├── tutorials/ # In-depth tutorials
│ ├── tutorial1.rst/md
│ └── tutorial2.rst/md
├── how-to/ # Task-oriented guides
│ ├── configure.rst/md
│ └── deploy.rst/md
├── api/ # API reference
│ ├── core.rst/md
│ └── utils.rst/md
├── changelog.rst/md # Version history
└── contributing.rst/md # How to contribute
Adding Badges
# Badges for README
[](https://pypi.org/project/my-package/)
[](https://pypi.org/project/my-package/)
[](https://my-package.readthedocs.io/)
[](https://github.com/user/my-package/actions)
[](https://codecov.io/gh/user/my-package)
[](https://github.com/user/my-package/blob/main/LICENSE)
Command Reference
Sphinx
sphinx-quickstart docs # Initialize Sphinx
make html # Build HTML
make clean # Clean build
sphinx-build -b html . _build # Build command
MkDocs
mkdocs new . # Initialize MkDocs
mkdocs serve # Local development server
mkdocs build # Build static site
mkdocs gh-deploy # Deploy to GitHub Pages
Next Steps
- Learn to Publish to PyPI with documented packages
- See our CLI Tools Guide for CLI documentation
- Explore the Python Packaging Complete Guide for the full ecosystem
For more Python development guides, explore our complete Python packaging series.