A Sphinx extension that builds an HTML gallery of examples from any set of Python scripts.
Conversion tools and command-line interface for working with Jupyter notebooks. Sphinx-Gallery provides bidirectional conversion between Python example scripts and Jupyter notebooks, enabling flexible documentation workflows.
Main command-line interface for converting Python scripts to Jupyter notebooks.
def python_to_jupyter_cli(args=None, namespace=None, sphinx_gallery_conf=None):
"""
Command-line interface for converting Python scripts to Jupyter notebooks.
Converts Python example scripts to Jupyter notebook format, preserving
code structure, comments, and output. Supports batch conversion of
multiple files and directories.
Parameters:
- args: list, command line arguments (optional, uses sys.argv if None)
- namespace: Namespace, parsed arguments object (optional)
- sphinx_gallery_conf: dict, gallery configuration for conversion options
Returns:
int: Exit code (0 for success, non-zero for error)
"""# Convert single file
sphinx_gallery_py2jupyter my_example.py
# Convert with output notebook name
sphinx_gallery_py2jupyter my_example.py -o output_notebook.ipynb
# Convert multiple files
sphinx_gallery_py2jupyter example1.py example2.py example3.py
# Convert with specific configuration
sphinx_gallery_py2jupyter my_example.py --gallery-conf-path ./conf.pyDirect Python function for converting scripts to notebooks.
def python_to_jupyter(python_src_file, example_nb_path, gallery_conf, target_dir):
"""
Convert Python script to Jupyter notebook.
Converts a Python example script to Jupyter notebook format,
parsing code blocks, markdown sections, and preserving structure.
Parameters:
- python_src_file: str, path to input Python script
- example_nb_path: str, path for output Jupyter notebook
- gallery_conf: dict, gallery configuration options
- target_dir: str, target directory for notebook
Returns:
str: Path to created notebook file
"""from sphinx_gallery.notebook import python_to_jupyter
gallery_conf = {
'first_notebook_cell': '# %% [markdown]\n# # Example Notebook\n',
'last_notebook_cell': '# %% [markdown]\n# ## Conclusion\n',
}
notebook_path = python_to_jupyter(
'examples/plot_example.py',
'notebooks/example.ipynb',
gallery_conf,
'notebooks/'
)Function for creating basic Jupyter notebook structure.
def jupyter_notebook_skeleton():
"""
Create basic Jupyter notebook structure.
Creates a minimal Jupyter notebook dictionary with proper
metadata and structure for adding cells.
Returns:
dict: Basic Jupyter notebook structure with metadata
"""{
"cells": [],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python",
"version": "3.x.x"
}
},
"nbformat": 4,
"nbformat_minor": 4
}Functions for converting between different cell types and formats.
def split_code_and_text_blocks(source_file, plot_gallery, gallery_conf):
"""
Split Python script into code and text blocks.
Parses a Python script and separates executable code from
documentation text blocks (docstrings and comments).
Parameters:
- source_file: str, path to Python script
- plot_gallery: bool, whether to include plot execution
- gallery_conf: dict, gallery configuration
Returns:
list: List of code and text block dictionaries
"""
def text_to_notebook_cell(text_block):
"""
Convert text block to Jupyter markdown cell.
Parameters:
- text_block: str, text content for cell
Returns:
dict: Jupyter markdown cell structure
"""
def code_to_notebook_cell(code_block):
"""
Convert code block to Jupyter code cell.
Parameters:
- code_block: str, Python code for cell
Returns:
dict: Jupyter code cell structure
"""Configure notebook generation through sphinx_gallery_conf:
sphinx_gallery_conf = {
# Add custom first cell
'first_notebook_cell': '''# %%
# Example Notebook
# ================
# This notebook was generated from a Python script.
''',
# Add custom last cell
'last_notebook_cell': '''# %%
# ## Next Steps
# Try modifying the code above and re-running the cells.
''',
# Control Jupyter magic promotion
'promote_jupyter_magic': True,
# Download format options
'download_all_examples': True, # Enables notebook downloads
}sphinx_gallery_conf = {
# Remove configuration comments from code cells
'remove_config_comments_from_code': True,
# Handle special code constructs
'promote_jupyter_magic': True, # Convert # %% to Jupyter magic
# Preserve module imports
'prefer_full_module': [], # Modules to import fully rather than from import
}def custom_notebook_processor(notebook_dict, gallery_conf):
"""
Custom processor for notebook modification.
Parameters:
- notebook_dict: dict, Jupyter notebook structure
- gallery_conf: dict, gallery configuration
Returns:
dict: Modified notebook structure
"""
# Add custom metadata
notebook_dict['metadata']['custom'] = {
'generated_by': 'sphinx-gallery',
'source': 'python_script'
}
# Modify cells
for cell in notebook_dict['cells']:
if cell['cell_type'] == 'code':
# Add execution count
cell['execution_count'] = None
elif cell['cell_type'] == 'markdown':
# Process markdown content
cell['source'] = process_markdown(cell['source'])
return notebook_dictimport os
from sphinx_gallery.notebook import python_to_jupyter
def convert_directory(src_dir, dest_dir, gallery_conf):
"""Convert all Python files in directory to notebooks."""
for filename in os.listdir(src_dir):
if filename.endswith('.py'):
src_path = os.path.join(src_dir, filename)
nb_name = filename.replace('.py', '.ipynb')
dest_path = os.path.join(dest_dir, nb_name)
python_to_jupyter(src_path, dest_path, gallery_conf, dest_dir)
print(f"Converted {filename} to {nb_name}")
# Usage
gallery_conf = {'first_notebook_cell': '# Generated Notebook\n'}
convert_directory('examples/', 'notebooks/', gallery_conf)# conf.py
def custom_notebook_build(app, env, docnames):
"""Custom notebook generation during Sphinx build."""
gallery_conf = app.config.sphinx_gallery_conf
# Convert specific examples to notebooks
examples = ['plot_basic.py', 'plot_advanced.py']
for example in examples:
src_path = os.path.join('examples', example)
nb_path = os.path.join('_build/notebooks', example.replace('.py', '.ipynb'))
python_to_jupyter(src_path, nb_path, gallery_conf, '_build/notebooks')
# Connect to Sphinx events
def setup(app):
app.connect('env-before-read-docs', custom_notebook_build)Sphinx-Gallery expects Python scripts with specific structure:
"""
Example Title
=============
This is the example description that becomes the first markdown cell.
Multiple paragraphs are supported and will be converted to markdown.
"""
# This comment becomes a markdown cell
# You can have multiple lines of comments
import matplotlib.pyplot as plt
import numpy as np
# Generate data
x = np.linspace(0, 10, 100)
y = np.sin(x)
# Create plot - this code becomes a code cell
plt.figure(figsize=(8, 6))
plt.plot(x, y)
plt.title('Sine Wave')
plt.show()
# %%
# This is a cell separator that creates explicit cell boundaries
# Anything after %% starts a new cell
print("This will be in a separate code cell")Automatic conversion of Jupyter magic commands:
# Input Python script:
# %matplotlib inline
import matplotlib.pyplot as plt
# Output notebook cell:
# %matplotlib inline
# import matplotlib.pyplot as pltRST-style formatting is converted to Markdown:
"""
Example with RST
================
This section demonstrates:
* List items
* **Bold text**
* ``Code snippets``
.. note::
This note will be converted to markdown.
"""Becomes:
# Example with RST
This section demonstrates:
* List items
* **Bold text**
* `Code snippets`
> **Note:** This note will be converted to markdown.Cell Separation: Use # %% comments to explicitly separate cells
Magic Commands: Enable promote_jupyter_magic for proper magic handling
Image Paths: Notebook image paths may need adjustment for relative references
Execution Order: Code cells are created in script execution order
sphinx_gallery_conf = {
'log_level': {'examples_log_level': 'DEBUG'},
'only_warn_on_example_error': True, # Continue on conversion errors
'abort_on_example_error': False, # Don't stop build on errors
}def validate_notebook(notebook_path):
"""Validate generated notebook structure."""
import json
with open(notebook_path, 'r') as f:
notebook = json.load(f)
# Check required fields
required_fields = ['cells', 'metadata', 'nbformat', 'nbformat_minor']
for field in required_fields:
assert field in notebook, f"Missing field: {field}"
# Check cell structure
for i, cell in enumerate(notebook['cells']):
assert 'cell_type' in cell, f"Cell {i} missing cell_type"
assert 'source' in cell, f"Cell {i} missing source"
print(f"Notebook {notebook_path} is valid")Install with Tessl CLI
npx tessl i tessl/pypi-sphinx-gallery