Overview
Sphinx is the de facto standard documentation generator for Python projects, originally created for the Python language documentation itself. It processes reStructuredText (reST) and Markdown source files and produces output in HTML, PDF (via LaTeX), ePub, man pages, and other formats. Sphinx supports cross-referencing, automatic API documentation from docstrings, theming, and an extensive extension ecosystem.
Sphinx is used by major projects including Python, Linux kernel, Django, and SQLAlchemy. It integrates seamlessly with Read the Docs for automated documentation hosting and supports internationalization through gettext-based workflows.
Installation
# Install via pip
pip install sphinx
# Install with common extras
pip install sphinx sphinx-autobuild sphinx-rtd-theme myst-parser
# Verify installation
sphinx-build --version
Quick Start
# Initialize a new Sphinx project
sphinx-quickstart docs
# Build HTML documentation
cd docs
make html
# Build PDF (requires LaTeX)
make latexpdf
# Auto-rebuild on changes
sphinx-autobuild source build/html
Project Structure
docs/
├── source/
│ ├── conf.py
│ ├── index.rst
│ ├── getting-started.rst
│ ├── api/
│ │ └── modules.rst
│ ├── _static/
│ ├── _templates/
│ └── _build/
├── Makefile
└── make.bat
Configuration (conf.py)
project = 'My Project'
copyright = '2024, My Team'
author = 'My Team'
release = '1.0.0'
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.napoleon',
'sphinx.ext.viewcode',
'sphinx.ext.intersphinx',
'sphinx.ext.todo',
'myst_parser',
]
templates_path = ['_templates']
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
source_suffix = {
'.rst': 'restructuredtext',
'.md': 'markdown',
}
html_theme = 'sphinx_rtd_theme'
html_static_path = ['_static']
intersphinx_mapping = {
'python': ('https://docs.python.org/3', None),
}
autodoc_member_order = 'bysource'
autodoc_typehints = 'description'
napoleon_google_docstring = True
napoleon_numpy_docstring = True
todo_include_todos = True
reStructuredText Syntax
Headings
Section Title
=============
Subsection
----------
Sub-subsection
^^^^^^^^^^^^^^
Inline Markup
| Syntax | Result |
|---|
*italic* | Italic text |
**bold** | Bold text |
code | Inline code |
:ref:`label` | Cross-reference |
:doc:`path` | Document link |
:func:`mymodule.func` | Function reference |
:class:`MyClass` | Class reference |
Directives
.. note::
This is a note admonition.
.. warning::
This is a warning.
.. code-block:: python
:linenos:
:emphasize-lines: 3,4
def hello():
name = "World"
print(f"Hello, {name}!")
.. image:: _static/screenshot.png
:width: 600px
:alt: Screenshot description
.. toctree::
:maxdepth: 2
:caption: Contents
getting-started
api/modules
changelog
Build Commands
| Command | Description |
|---|
make html | Build HTML documentation |
make latexpdf | Build PDF via LaTeX |
make epub | Build ePub format |
make man | Build man pages |
make text | Build plain text |
make linkcheck | Check all external links |
make doctest | Run code examples as tests |
make coverage | Check documentation coverage |
make clean | Remove build directory |
Autodoc (API Documentation)
Generate API Stubs
sphinx-apidoc -o docs/source/api src/mypackage --separate --force
Google Style Docstrings
def calculate_area(length: float, width: float) -> float:
"""Calculate the area of a rectangle.
Args:
length: The length of the rectangle.
width: The width of the rectangle.
Returns:
The area of the rectangle.
Raises:
ValueError: If length or width is negative.
"""
if length < 0 or width < 0:
raise ValueError("Dimensions must be non-negative")
return length * width
In reST Files
.. automodule:: mypackage.core
:members:
:undoc-members:
:show-inheritance:
.. autofunction:: mypackage.utils.helper_func
Advanced Usage
MyST Markdown Support
pip install myst-parser
# conf.py
extensions = ['myst_parser']
myst_enable_extensions = [
"colon_fence",
"deflist",
"tasklist",
]
Custom Extensions
# docs/source/_ext/my_extension.py
from docutils import nodes
from sphinx.util.docutils import SphinxDirective
class MyDirective(SphinxDirective):
has_content = True
required_arguments = 1
def run(self):
text = '\n'.join(self.content)
node = nodes.paragraph(text=text)
return [node]
def setup(app):
app.add_directive('my-directive', MyDirective)
return {'version': '0.1', 'parallel_read_safe': True}
Troubleshooting
| Issue | Solution |
|---|
| autodoc not finding modules | Add source path to sys.path in conf.py |
| LaTeX PDF build fails | Install texlive-full or equivalent TeX distribution |
| Cross-references not resolving | Use correct role syntax (:func:, :class:, etc.) |
| Theme not applying | Install theme package and set html_theme in conf.py |
| Build warnings about missing toctree | Add all documents to a toctree directive |
| Intersphinx links broken | Verify URL and run make clean then rebuild |
| Encoding errors | Ensure all source files are UTF-8 encoded |
| Slow builds with many files | Use sphinx-build -j auto for parallel builds |