Sphinx
GitHub Overview
sphinx-doc/sphinx
The Sphinx documentation generator
Topics
Star History
Documentation Tool
Sphinx
Overview
Sphinx is a powerful documentation generation tool developed in Python. Based on reStructuredText (rST), it provides rich functionality specialized for API documentation auto-generation, academic paper writing, and technical documentation creation.
Details
Sphinx was developed by Georg Brandl in 2008 and has established itself as the standard documentation tool for the Python community. Initially created for Python's official documentation, it is now used by many projects including Python, Django, and Flask. Using the reStructuredText markup language, it enables creation of structured, high-quality documentation. The autodoc extension automatically generates API documentation from Python code. It covers comprehensive features needed for academic document creation including mathematical notation, cross-references, index generation, and multi-language support. It supports various output formats (HTML, PDF, ePub, LaTeX, etc.), allowing generation of multiple format documents from a single source. Rich themes and extensions provide customizability and extensibility. The Napoleon extension also supports Google-style and NumPy-style docstrings. As of 2025, popular themes like Read the Docs, Alabaster, and Furo enable beautiful and functional documentation sites. Through Sphinx-autodoc for API documentation automation, Sphinx-gallery for example collections, and sphinx-needs for requirements management extensions, it provides a professional documentation creation environment.
Advantages and Disadvantages
Advantages
- API Documentation Auto-generation: Automatic API reference creation from Python code docstrings
- Multiple Output Formats: Rich output formats including HTML, PDF, ePub, LaTeX, man pages
- Academic Document Support: Mathematical formulas, citations, indexes, cross-references for academic paper creation
- Rich Extensions: Diverse extension functionality for todo management, diagram generation, test execution
- Professional Quality: Publication-level high-quality document output
- Theme System: Beautiful themes like Read the Docs, Alabaster, Furo
- Internationalization Support: Efficient management and localization of multilingual documents
Disadvantages
- Learning Curve: Time required to master reStructuredText syntax and Sphinx configuration
- Python Dependency: Requires Python environment and knowledge of Python ecosystem
- Complex Configuration: Configuration file (conf.py) complexity when using advanced features
- No Markdown Support: No default Markdown support (can be added with extensions)
- Build Time: Increased documentation generation time for large-scale projects
- Design Limitations: CSS/HTML expertise required for theme customization
Key Links
- Sphinx Official Site
- Sphinx Documentation
- GitHub Repository
- Read the Docs Theme
- Extensions List
- Sphinx Examples Gallery
Usage Examples
Project Initialization
# Install Sphinx
pip install sphinx
# Create project
sphinx-quickstart docs
# Project structure
docs/
├── _build/ # Generated documentation
├── _static/ # Static files (CSS, JS, images)
├── _templates/ # Custom templates
├── conf.py # Configuration file
├── index.rst # Main page
└── make.bat # Windows build script
Basic conf.py Configuration
# Configuration file for the Sphinx documentation builder.
# -- Project information -----------------------------------------------------
project = 'Project Name'
copyright = '2025, Author Name'
author = 'Author Name'
release = '1.0.0'
# -- General configuration ---------------------------------------------------
extensions = [
'sphinx.ext.autodoc', # API documentation auto-generation
'sphinx.ext.autosummary', # Auto-generation of summaries
'sphinx.ext.napoleon', # Google/NumPy style docstrings
'sphinx.ext.viewcode', # Links to source code
'sphinx.ext.intersphinx', # Cross-references with other projects
'sphinx.ext.mathjax', # Mathematical notation support
'sphinx.ext.githubpages', # GitHub Pages support
'sphinx.ext.todo', # TODO list management
]
# Templates path
templates_path = ['_templates']
# Language settings
language = 'en'
# Exclude patterns
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# -- Options for HTML output ------------------------------------------------
html_theme = 'sphinx_rtd_theme'
html_static_path = ['_static']
html_title = 'Project Documentation'
html_short_title = 'Project'
html_logo = '_static/logo.png'
html_favicon = '_static/favicon.ico'
# Theme options
html_theme_options = {
'analytics_id': 'G-XXXXXXXXXX',
'logo_only': False,
'display_version': True,
'prev_next_buttons_location': 'bottom',
'style_external_links': False,
'vcs_pageview_mode': '',
'style_nav_header_background': '#2980B9',
'collapse_navigation': True,
'sticky_navigation': True,
'navigation_depth': 4,
'includehidden': True,
'titles_only': False
}
# -- Options for LaTeX output -----------------------------------------------
latex_elements = {
'papersize': 'letterpaper',
'pointsize': '10pt',
'preamble': r'''
\usepackage[utf8]{inputenc}
''',
}
latex_documents = [
('index', 'project.tex', 'Project Documentation',
'Author Name', 'manual'),
]
# -- Napoleon settings ------------------------------------------------------
napoleon_google_docstring = True
napoleon_numpy_docstring = True
napoleon_include_init_with_doc = False
napoleon_include_private_with_doc = False
napoleon_include_special_with_doc = True
napoleon_use_admonition_for_examples = False
napoleon_use_admonition_for_notes = False
napoleon_use_admonition_for_references = False
napoleon_use_ivar = False
napoleon_use_param = True
napoleon_use_rtype = True
# -- Autodoc settings -------------------------------------------------------
autodoc_default_options = {
'members': True,
'member-order': 'bysource',
'special-members': '__init__',
'undoc-members': True,
'exclude-members': '__weakref__'
}
# -- Todo extension settings ------------------------------------------------
todo_include_todos = True
# -- Intersphinx mapping ----------------------------------------------------
intersphinx_mapping = {
'python': ('https://docs.python.org/3', None),
'django': ('https://docs.djangoproject.com/en/stable/', None),
'numpy': ('https://numpy.org/doc/stable/', None),
}
Basic reStructuredText Syntax
==================
Project Title
==================
.. contents:: Table of Contents
:depth: 2
Overview
========
This project demonstrates API documentation generation examples.
API Reference
=============
Module List
-----------
.. autosummary::
:toctree: generated
:recursive:
myproject.core
myproject.utils
myproject.models
Detailed API
------------
.. automodule:: myproject.core
:members:
:undoc-members:
:show-inheritance:
.. autoclass:: myproject.models.User
:members:
:special-members: __init__
Mathematical Examples
=====================
Inline math: :math:`E = mc^2`
Block math:
.. math::
\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}
Notes and Admonitions
=====================
.. note::
This is a note.
.. warning::
This is a warning.
.. tip::
This is a helpful tip.
.. seealso::
Related information: :doc:`installation`
Code Blocks
===========
Python code example:
.. code-block:: python
:linenos:
:emphasize-lines: 3,5
def hello_world(name):
"""Greeting function
Args:
name (str): Name
Returns:
str: Greeting message
"""
return f"Hello, {name}!"
# Usage example
message = hello_world("World")
print(message)
Tables
======
.. csv-table:: Feature Comparison
:header: "Feature", "Support", "Notes"
:widths: 30, 20, 50
"Auto-generation", "✓", "Auto-generated from Python code"
"Themes", "✓", "Multiple themes available"
"PDF Output", "✓", "PDF generation via LaTeX"
"Multilingual", "✓", "Internationalization support"
Figures
=======
.. figure:: _static/architecture.png
:alt: System architecture diagram
:align: center
:width: 80%
Overall system architecture
Cross-references
================
- Section reference: :ref:`api-reference`
- Document reference: :doc:`installation`
- External reference: :py:func:`json.dumps`
- Glossary: :term:`API`
.. glossary::
API
Application Programming Interface
TODO List
=========
.. todo::
Implement user authentication feature
.. todolist::
Automatic API Documentation Generation
# sample_module.py - Sample Python module
"""
Sample module
This module demonstrates Sphinx's autodoc functionality.
"""
from typing import List, Optional, Dict, Any
import json
class DataProcessor:
"""Data processing class
A class that provides various data processing operations.
Attributes:
data (List[Any]): List of data to process
config (Dict[str, Any]): Configuration information
Example:
>>> processor = DataProcessor([1, 2, 3, 4, 5])
>>> result = processor.filter_data(lambda x: x > 3)
>>> print(result)
[4, 5]
"""
def __init__(self, data: List[Any], config: Optional[Dict[str, Any]] = None):
"""Constructor
Args:
data: List of data to process
config: Optional configuration. Defaults to None
Raises:
ValueError: If data is empty
"""
if not data:
raise ValueError("Data list cannot be empty")
self.data = data
self.config = config or {}
def filter_data(self, condition) -> List[Any]:
"""Filter data based on condition
Args:
condition (callable): Function defining filtering condition
Returns:
List[Any]: Filtered data list
Raises:
TypeError: If condition is not callable
Note:
This function does not modify the original data. Returns a new list.
Warning:
Be careful of memory usage when processing large amounts of data.
"""
if not callable(condition):
raise TypeError("condition must be callable")
return [item for item in self.data if condition(item)]
def transform_data(self, transformer) -> List[Any]:
"""Transform data
Args:
transformer (callable): Transformation function
Returns:
List[Any]: Transformed data list
"""
return [transformer(item) for item in self.data]
def save_to_json(self, filename: str) -> None:
"""Save data to JSON file
Args:
filename: Target filename
Raises:
IOError: If file writing fails
"""
try:
with open(filename, 'w', encoding='utf-8') as f:
json.dump(self.data, f, ensure_ascii=False, indent=2)
except Exception as e:
raise IOError(f"Failed to save file: {e}")
def calculate_statistics(data: List[float]) -> Dict[str, float]:
"""Calculate statistical information
Calculates basic statistical values from a list of numbers.
Args:
data: List of numbers
Returns:
Dictionary containing statistical information
* mean: Average value
* median: Median value
* std: Standard deviation
* min: Minimum value
* max: Maximum value
Raises:
ValueError: If data is empty or contains non-numeric values
Example:
>>> stats = calculate_statistics([1, 2, 3, 4, 5])
>>> print(f"Mean: {stats['mean']}")
Mean: 3.0
See Also:
:py:class:`DataProcessor`: More advanced data processing features
"""
if not data:
raise ValueError("Data list is empty")
if not all(isinstance(x, (int, float)) for x in data):
raise ValueError("All elements must be numeric")
n = len(data)
mean = sum(data) / n
sorted_data = sorted(data)
# Calculate median
if n % 2 == 0:
median = (sorted_data[n//2 - 1] + sorted_data[n//2]) / 2
else:
median = sorted_data[n//2]
# Calculate standard deviation
variance = sum((x - mean) ** 2 for x in data) / n
std = variance ** 0.5
return {
'mean': mean,
'median': median,
'std': std,
'min': min(data),
'max': max(data)
}
Creating Sphinx Extensions
# sphinx_extension_example.py - Custom Sphinx extension
from docutils import nodes
from docutils.parsers.rst import Directive
from sphinx.application import Sphinx
from sphinx.util.docutils import SphinxDirective
class TodoDirective(SphinxDirective):
"""Custom TODO directive"""
has_content = True
required_arguments = 0
optional_arguments = 1
final_argument_whitespace = True
option_spec = {
'priority': str,
'assigned': str,
'due': str,
}
def run(self):
"""Execute directive"""
env = self.state.document.settings.env
# Create TODO node
todo_node = todo('')
todo_node['priority'] = self.options.get('priority', 'medium')
todo_node['assigned'] = self.options.get('assigned', '')
todo_node['due'] = self.options.get('due', '')
# Parse content
self.state.nested_parse(self.content, self.content_offset, todo_node)
# Add TODO to environment
if not hasattr(env, 'todo_all_todos'):
env.todo_all_todos = []
env.todo_all_todos.append({
'docname': env.docname,
'lineno': self.lineno,
'todo': todo_node.deepcopy(),
'target': nodes.target(),
})
return [todo_node]
class todo(nodes.Admonition, nodes.Element):
"""TODO node class"""
pass
def visit_todo_node(self, node):
"""Visit TODO node (HTML output)"""
priority = node.get('priority', 'medium')
assigned = node.get('assigned', '')
due = node.get('due', '')
attrs = {'class': f'todo priority-{priority}'}
self.body.append(self.starttag(node, 'div', **attrs))
# Add header information
self.body.append('<div class="todo-header">')
self.body.append(f'<span class="todo-priority">Priority: {priority}</span>')
if assigned:
self.body.append(f'<span class="todo-assigned">Assigned: {assigned}</span>')
if due:
self.body.append(f'<span class="todo-due">Due: {due}</span>')
self.body.append('</div>')
def depart_todo_node(self, node):
"""Depart TODO node (HTML output)"""
self.body.append('</div>\n')
def purge_todos(app, env, docname):
"""Clean up TODOs when document is removed"""
if not hasattr(env, 'todo_all_todos'):
return
env.todo_all_todos = [todo for todo in env.todo_all_todos
if todo['docname'] != docname]
def merge_todos(app, env, docnames, other):
"""Merge TODOs when merging environments"""
if not hasattr(env, 'todo_all_todos'):
env.todo_all_todos = []
if hasattr(other, 'todo_all_todos'):
env.todo_all_todos.extend(other.todo_all_todos)
def process_todo_nodes(app, doctree, fromdocname):
"""Post-process TODO nodes"""
if not app.config.todo_include_todos:
for node in doctree.traverse(todo):
node.parent.remove(node)
def setup(app: Sphinx):
"""Extension setup"""
app.add_config_value('todo_include_todos', False, 'html')
app.add_node(todo,
html=(visit_todo_node, depart_todo_node),
latex=(visit_todo_node, depart_todo_node),
text=(visit_todo_node, depart_todo_node))
app.add_directive("todo", TodoDirective)
app.connect('doctree-resolved', process_todo_nodes)
app.connect('env-purge-doc', purge_todos)
app.connect('env-merge-info', merge_todos)
return {
'version': '0.1',
'parallel_read_safe': True,
'parallel_write_safe': True,
}
Theme Customization
# Custom theme configuration (in conf.py)
# -- HTML output options ----------------------------------------------------
html_theme = 'sphinx_rtd_theme'
# Custom CSS
html_css_files = [
'custom.css',
]
# Custom JavaScript
html_js_files = [
'custom.js',
]
# Detailed theme options
html_theme_options = {
# Site settings
'analytics_id': 'G-XXXXXXXXXX',
'analytics_anonymize_ip': False,
# Logo and title
'logo_only': False,
'display_version': True,
# Navigation
'prev_next_buttons_location': 'bottom',
'style_external_links': False,
'vcs_pageview_mode': '',
# Sidebar
'collapse_navigation': True,
'sticky_navigation': True,
'navigation_depth': 4,
'includehidden': True,
'titles_only': False,
# Appearance
'style_nav_header_background': '#2980B9',
}
# Sidebar configuration
html_sidebars = {
'**': [
'about.html',
'navigation.html',
'relations.html',
'searchbox.html',
'donate.html',
]
}
Automated Deployment Configuration
# .github/workflows/docs.yml - GitHub Actions
name: Build and Deploy Documentation
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: 3.x
- name: Install dependencies
run: |
pip install -r docs/requirements.txt
- name: Build documentation
run: |
cd docs
sphinx-build -b html . _build/html
- name: Deploy to GitHub Pages
if: github.ref == 'refs/heads/main'
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: docs/_build/html
Development Workflow
# Start development server (auto-rebuild)
sphinx-autobuild docs docs/_build/html
# Standard build commands
cd docs
make html # Generate HTML
make latexpdf # Generate PDF
make epub # Generate ePub
make man # Generate man pages
# Rebuild specific files only
sphinx-build -b html -a docs docs/_build/html
# Clean build
make clean
make html
# Auto-generate API documentation
sphinx-apidoc -o docs/source myproject
# Multilingual build
make gettext # Generate translation templates
sphinx-intl update -p docs/_build/gettext -l ja # Add Japanese support
make -e SPHINXOPTS="-D language='ja'" html # Generate Japanese version