高级用法#
如果您想更深入地了解如何使用 Sphinx-Gallery,本页包含更多高级主题。
扩展您的 Sphinx-Gallery Makefile#
本节描述了一些对 Sphinx-Gallery 有用的文档 Makefile 的常见扩展。
清理画廊文件#
一旦您的画廊开始工作,您可能需要完全删除 Sphinx-Gallery 生成的所有文件,以获得干净的构建。为此,我们建议将以下内容添加到您的 Sphinx Makefile
clean:
rm -rf $(BUILDDIR)/*
rm -rf auto_examples/
如果您更改了 gallery_dirs
配置变量,则需要调整第二个 rm
命令。
在不运行任何示例的情况下构建画廊#
如果您希望在不先运行示例的情况下构建您的画廊(例如,如果示例运行时间很长),请将以下内容添加到您的 Makefile
。
html-noplot:
$(SPHINXBUILD) -D plot_gallery=0 -b html $(ALLSPHINXOPTS) $(SOURCEDIR) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
了解您的画廊文件#
画廊已构建,现在您和您项目的所有用户都可以开始使用它了。生成画廊所需的所有临时文件(rst 文件、图像、缓存对象等)都存储在您在 gallery_dirs
中配置的位置。最终进入您文档的 HTML 版本的文件具有一个特定的命名空间,以避免与您自己的文件和图像发生冲突。
我们的命名空间约定是在所有内容前面添加 sphx_glr
并将路径分隔符替换为下划线。例如,示例“plot_0_sin.py”生成的第一个图像的名称为 sphx_glr_plot_0_sin_001.png
,其缩略图名称为 sphx_glr_plot_0_sin_thumb.png
您还可以使用 literalinclude
指令将画廊脚本的一部分包含在您文档的其他地方,以限制代码重复
.. literalinclude:: ../examples/plot_0_sin.py
:language: python
:start-after: # License: BSD 3 clause
:end-before: # To avoid matplotlib
上面的指令插入以下块
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 2 * np.pi, 100)
y = np.sin(x)
plt.plot(x, y)
plt.xlabel(r"$x$")
plt.ylabel(r"$\sin(x)$")
警告
使用 literalinclude 比较脆弱,当示例发生更改时很容易出现故障(尤其是在使用行号而不是 start-after
和 end-before
时)。谨慎使用:直接链接到示例是一种更可靠的替代方法。
交叉引用#
您还可以使用类似的命名约定交叉引用示例。例如,如果我们要引用示例 入门示例 - 绘制正弦曲线,我们只需调用它的引用 :ref:`sphx_glr_auto_examples_plot_0_sin.py`
。请注意,我们在 sphx_glr_
后面包含了示例文件的路径(相对于 conf.py
文件)。路径分隔符被替换为下划线。
理解警告和错误输出#
在画廊 Python 文件中执行代码块时出现的任何警告或错误将在构建文档时以粉色显示。还会打印 .py
文件路径和发生错误的行号。例如,示例 无法执行的示例 将引发以下错误
File "<full_path>/examples/no_output/plot_raise.py", line 27, in <module>
iae
NameError: name 'iae' is not defined
画廊 Python 文件的文本(reST)块中的问题会导致 Sphinx 将生成的 .rst
文件转换为 HTML 时出现警告或错误。这些将在构建文档时,在代码块错误之后以粉色显示,由 Sphinx 打印。在这种情况下,将打印 .rst
文件路径和 .rst
文件行号。要解决问题,您需要修改原始的 .py
文件,而不是生成的 .rst
文件。要确定问题所在,您需要将打印的行号处的 .rst
文件内容与原始的 .py
文件进行匹配。
示例 .rst
警告
<full_path>/auto_examples/plot_example.rst:19: WARNING: Explicit markup ends without a blank line; unexpected unindent.
上面的警告是由于 plot_example.rst
中的第 19 行引起的。需要修改原始的 plot_example.py
文件才能修复它。Sphinx-Gallery 只会(重新)构建新的、修改过的或失败的示例,因此重新运行文档构建应该只重建修改过的示例,从而允许快速迭代。
编写自定义图像抓取器#
警告
自定义抓取器的 API 目前处于实验阶段。
默认情况下,Sphinx-Gallery 支持 Matplotlib 的图像抓取 (matplotlib_scraper()
)。如果您希望捕获来自其他 Python 包的输出,首先确定您要捕获的对象是否具有 _repr_html_
方法。如果是,您可以使用配置 capture_repr
(控制捕获的输出) 来控制对象的显示,而无需编写自定义抓取器。此配置允许捕获原始 html 输出,该过程类似于其他基于 html 的显示,例如 jupyter。如果第一个选项不起作用,本节描述如何编写自定义抓取器。
图像抓取器是函数(或可调用类实例),它们执行以下操作
收集代码最新执行中创建的图像列表。
将这些图像以 PNG、JPEG、SVG、GIF 或 WebP 格式写入磁盘(分别使用 .png、.jpg、.svg、.gif 或 .webp 扩展名)
返回将这些图形嵌入到构建的文档中的 reST。
该函数应采用以下输入(按此顺序)
block
- Sphinx-Gallery.py
文件被分成连续的“代码”行和 reST“文本”,称为“块”。对于每个块,都会创建一个带有 (“type”, “content”, “lineno”) 项目的 namedtuple(例如('code', 'print("Hello world")', 5)
)。“label”是一个字符串,可以是
'text'
或'code'
。在这种情况下,它应该只是'code'
,因为此函数仅针对代码块调用。“content”是一个包含代码块实际内容的字符串。
“lineno”是一个整数,表示块开始的行号。
block_vars
- 配置和运行时变量的字典。对于图像抓取器来说,感兴趣的是元素'image_path_iterator'
,它是一个可迭代对象,返回符合 Sphinx-Gallery 命名约定的图像文件名的绝对路径。该路径指向gallery_dirs/images
目录 (配置和使用 Sphinx-Gallery),图像文件名是'sphx_glr_'
后跟源.py
文件的名称,然后是一个数字,该数字从 1 开始,在每次迭代时增加 1。默认文件格式是.'png'
。例如:'home/user/Documents/module/auto_examples/images/sphx_glr_plot_mymodule_001.png'
。如果需要其他图像扩展名,则抓取器负责替换默认的 .png 扩展名。只有支持的图像扩展名(见上文)才能使文件被 Sphinx-Gallery 拾取。gallery_conf
- 包含 Sphinx-Gallery 配置的字典,设置在doc/conf.py
(配置) 中的sphinx_gallery_conf
下。需要注意的是,image_srcset 配置将提供用户指定的图像分辨率(作为浮点数),您的自定义抓取器可以使用它来启用多分辨率图像。
它应该返回一个包含用于将此图片嵌入文档的 reST 的字符串。请参阅 matplotlib_scraper()
查看刮取器函数的示例(点击函数名称下方的“源代码”查看源代码)。matplotlib_scraper()
使用辅助函数 sphinx_gallery.scrapers.figure_rst()
来帮助生成 reST(见下文)。
此函数将为您的每个示例代码块调用一次。Sphinx-Gallery 将负责为图库索引页缩略图缩放图像。PNG、JPEG 和 WebP 图像使用 Pillow 进行缩放,而 SVG 和 GIF 图像则被复制。
警告
SVG 图像不适用于 latex
构建模式,因此在构建文档的 PDF 版本时不会生效。您可能需要考虑使用 sphinxcontrib-svg2pdfconverter。
示例 1:Matplotlib 风格的刮取器#
例如,我们将展示一个假设包的刮取器示例代码。它使用了一种类似于 sphinx_gallery.scrapers.matplotlib_scraper()
在后台所做的事情的方法,它使用辅助函数 sphinx_gallery.scrapers.figure_rst()
来创建标准化的 reST。如果您的包将用于将图像文件写入磁盘(例如,PNG 或 JPEG),我们建议您使用类似的方法。
def my_module_scraper(block, block_vars, gallery_conf):
import mymodule
# We use a list to collect references to image names
image_names = list()
# The `image_path_iterator` is created by Sphinx-Gallery, it will yield
# a path to a file name that adheres to Sphinx-Gallery naming convention.
image_path_iterator = block_vars['image_path_iterator']
# Define a list of our already-created figure objects.
list_of_my_figures = mymodule.get_figures()
# Iterate through figure objects, save to disk, and keep track of paths.
for fig, image_path in zip(list_of_my_figures, image_path_iterator):
fig.save_png(image_path)
image_names.append(image_path)
# Close all references to figures so they aren't used later.
mymodule.close('all')
# Use the `figure_rst` helper function to generate the reST for this
# code block's figures. Alternatively you can define your own reST.
return figure_rst(image_names, gallery_conf['src_dir'])
此代码可以在您的 conf.py
文件中定义,也可以作为您导入到 conf.py
文件中的模块(请参阅 导入可调用对象)。使用此刮取器所需的配置如下所示:
sphinx_gallery_conf = {
...
'image_scrapers': ('matplotlib', "my_module._scraper.my_module_scraper"),
}
Sphinx-Gallery 将解析字符串 "my_module._scraper.my_module_scraper"
来导入可调用函数。
示例 2:检测磁盘上的图像文件#
这里还有另一个示例,假设图像已经写入磁盘。在这种情况下,我们不会生成任何图像文件,只会生成将它们嵌入文档中所需的 reST。请注意,示例脚本仍然需要执行以刮取文件,但图像不需要在执行期间生成。
我们假设该函数在您包中名为 _scraper
的模块中定义。以下是刮取器代码:
from glob import glob
import shutil
import os
from sphinx_gallery.scrapers import figure_rst
def png_scraper(block, block_vars, gallery_conf):
# Find all PNG files in the directory of this example.
path_current_example = os.path.dirname(block_vars['src_file'])
pngs = sorted(glob(os.path.join(path_current_example, '*.png')))
# Iterate through PNGs, copy them to the Sphinx-Gallery output directory
image_names = list()
image_path_iterator = block_vars['image_path_iterator']
seen = set()
for png in pngs:
if png not in seen:
seen |= set(png)
this_image_path = image_path_iterator.next()
image_names.append(this_image_path)
shutil.move(png, this_image_path)
# Use the `figure_rst` helper function to generate reST for image files
return figure_rst(image_names, gallery_conf['src_dir'])
然后,在我们的 conf.py
文件中,我们包含以下代码:
sphinx_gallery_conf = {
...
'image_scrapers': ('matplotlib', 'my_module._scraper.png_scraper'),
}
示例 3:使用 SVG 格式的 matplotlib#
sphinx_gallery.scrapers.matplotlib_scraper()
支持 **kwargs
传递给 matplotlib.figure.Figure.savefig()
,其中之一是 format
参数。请参阅 编写自定义图像刮取器 以了解支持的格式。要使用 SVG,您可以定义以下函数并确保它可以 导入:
def matplotlib_svg_scraper(*args, **kwargs):
return matplotlib_scraper(*args, format='svg', **kwargs)
然后在您的 conf.py
中:
sphinx_gallery_conf = {
...
'image_scrapers': ("sphinxext.matplotlib_svg_scraper",),
...
}
您也可以在每个图像的基础上使用不同的格式,但这需要编写自定义的刮取器类或函数。
示例 4:Mayavi 刮取器#
历史上,Sphinx-Gallery 除了支持刮取 matplotlib 图像外,还支持刮取 Mayavi 图像。但是,由于维护刮取器很复杂,因此在 0.12.0 版本中弃用了对它的支持。要继续使用 Mayavi 刮取,请考虑使用以下内容:
from sphinx_gallery.scrapers import figure_rst
def mayavi_scraper(self, block, block_vars, gallery_conf):
from mayavi import mlab
image_path_iterator = block_vars['image_path_iterator']
image_paths = list()
e = mlab.get_engine()
for scene, image_path in zip(e.scenes, image_path_iterator):
try:
mlab.savefig(image_path, figure=scene)
except Exception:
mlab.close(all=True)
raise
# make sure the image is not too large
scale_image(image_path, image_path, 850, 999)
if 'images' in gallery_conf['compress_images']:
optipng(image_path, gallery_conf['compress_images_args'])
image_paths.append(image_path)
mlab.close(all=True)
return figure_rst(image_paths, gallery_conf['src_dir'])
将自定义刮取器与 Sphinx-Gallery 集成#
Sphinx-Gallery 计划只在内部维护一个刮取器:matplotlib。如果您扩展或修复了此刮取器的错误,我们欢迎您提交 PR 来改进它!
另一方面,如果您为另一个绘图库开发了一个自定义刮取器,这对更广泛的社区来说很有用,我们鼓励您让它与 Sphinx-Gallery 协同工作,然后在外部维护它(可能在它刮取的包中),然后将其与 Sphinx-Gallery 集成并宣传它。您可以:
将它贡献到位于 重置模块 中的外部支持的刮取器列表中。
可选:在您的模块根目录中添加一个自定义钩子来简化刮取器的使用。以 PyVista 为例,添加
pyvista._get_sg_image_scraper()
,它返回由 Sphinx-Gallery 使用的可调用刮取器,允许 PyVista 用户像他们已经可以对'matplotlib'
做的那样使用字符串。sphinx_gallery_conf = { ... 'image_scrapers': ('pyvista',) }
Sphinx-Gallery 将导入命名的模块(这里为
pyvista
),并使用在那里定义的_get_sg_image_scraper
函数作为刮取器。
在每个示例之前重置#
Sphinx-Gallery 支持在执行每个示例脚本之前和/或之后运行的“重置”函数。它在 Sphinx-Gallery 中被原生用于“重置”可视化包 matplotlib
和 seaborn
的行为(重置模块)。但是,此功能可用于重置其他库,修改原生重置库的重置行为或在每个脚本的开头和/或结尾运行任意自定义函数。
这是通过在 conf.py
中定义的重置元组中添加自定义函数来完成的。该函数应采用两个变量:一个名为 gallery_conf
的字典(它包含您的 Sphinx-Gallery 配置)和一个名为 fname
的字符串(它包含当前执行的 Python 脚本的文件名)。通常不需要使用它们来执行您想要的任何重置行为,但出于兼容性原因,它们必须包含在函数定义中。
例如,要将 matplotlib 重置为始终使用 ggplot
样式,您可以执行以下操作:
def reset_mpl(gallery_conf, fname):
from matplotlib import style
style.use('ggplot')
任何自定义函数都可以在 conf.py
中定义(或导入),并传递给 reset_modules
配置键。要添加上面定义的函数(假设您已将其 导入):
sphinx_gallery_conf = {
...
'reset_modules': ("sphinxext.reset_mpl", "seaborn"),
}
在上面的配置中,"seaborn"
指的是原生 seaborn 重置函数(请参阅 重置模块)。
注意:
使用像 reset_mpl
这样的重置器,它们偏离了用户在手动运行示例时会遇到的标准行为,这是不鼓励的,因为这会导致呈现的示例与本地输出之间出现不一致。
如果自定义函数需要知道它是在示例之前还是之后运行,则可以使用具有三个参数的函数签名,其中第三个参数必须命名为 when
def reset_mpl(gallery_conf, fname, when):
import matplotlib as mpl
mpl.rcParams['lines.linewidth'] = 2
if when == 'after' and fname=='dashed_lines':
mpl.rcParams['lines.linestyle'] = '-'
传递给 when
的值可以是 'before'
或 'after'
。如果 配置 中的 reset_modules_order
设置为 'before'
或 'after'
,则 when
将始终与 reset_modules_order
设置的值相同。此函数签名只有在与 reset_modules_order
设置为 'both'
结合使用时才有用。
更改 Sphinx-Gallery CSS#
控制示例图库外观的 Sphinx-Gallery .css
文件可以在 这里 找到。这些默认的 .css
文件将被添加到您的构建中。具体来说,它们将被复制到您的 gallery_dir
的 _build/html/_static/
中。
您可以通过使用 Sphinx 配置 html_static_path
添加您自己的自定义 .css
文件。例如,使用 html_static_path
配置列出包含您自定义静态文件的任何路径,在您的 conf.py
文件中:
html_static_path = ['_static']
# Custom CSS paths should either relative to html_static_path
# or fully qualified paths (eg. https://...)
html_css_files = ['my_custom.css', 'other_change.css']
默认的 Sphinx-Gallery .css
文件将在您 html_static_path
配置中的文件之后复制到您的构建中。这意味着,如果您 html_static_path
中的文件与 Sphinx-Gallery .css
文件同名,它们将被覆盖。您可以轻松避免这种情况,因为所有 Sphinx-Gallery .css
文件都在前面加上了“sg_”(例如,“sg_gallery.css”)。有关这方面的更多详细信息,请参阅 PR #845。
例如,自定义 CSS 可用于更改代码链接和缩略图大小的外观。
禁用悬停时的缩略图文本#
.sphx-glr-thumbcontainer[tooltip]:hover::before,
.sphx-glr-thumbcontainer[tooltip]:hover::after {
display: none;
}
使用(仅)Sphinx-Gallery 样式#
如果您只想使用 sphinx-Gallery CSS 文件,而不是使用 sphinx_gallery.gen_gallery
扩展,您可以在 conf.py
中使用
extensions = ['sphinx_gallery.load_style']
这只会导致 gallery.css
文件添加到您的构建中。