高级用法#

如果您想更深入地了解如何使用 Sphinx-Gallery,本页包含更多高级主题。

理解警告和错误输出#

在画廊 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。如果第一个选项不起作用,本节描述如何编写自定义抓取器。

图像抓取器是函数(或可调用类实例),它们执行以下操作

  1. 收集代码最新执行中创建的图像列表。

  2. 将这些图像以 PNG、JPEG、SVG、GIF 或 WebP 格式写入磁盘(分别使用 .png、.jpg、.svg、.gif 或 .webp 扩展名)

  3. 返回将这些图形嵌入到构建的文档中的 reST。

该函数应采用以下输入(按此顺序)

  1. block - Sphinx-Gallery .py 文件被分成连续的“代码”行和 reST“文本”,称为“块”。对于每个块,都会创建一个带有 (“type”, “content”, “lineno”) 项目的 namedtuple(例如 ('code', 'print("Hello world")', 5))。

    • “label”是一个字符串,可以是 'text''code'。在这种情况下,它应该只是 'code',因为此函数仅针对代码块调用。

    • “content”是一个包含代码块实际内容的字符串。

    • “lineno”是一个整数,表示块开始的行号。

  2. 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 拾取。

  3. 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 中被原生用于“重置”可视化包 matplotlibseaborn 的行为(重置模块)。但是,此功能可用于重置其他库,修改原生重置库的重置行为或在每个脚本的开头和/或结尾运行任意自定义函数。

这是通过在 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' 结合使用时才有用。