進階用法#

本頁包含更進階的主題,以防您想更深入了解如何使用 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() 以了解擷取器函式的範例 (點擊函式名稱下方的「source」即可查看原始碼)。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 支援擷取 Mayavi 圖形以及 matplotlib 圖形。然而,由於維護擷取器的複雜性,此支援已在 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 的設定值相同。此函式簽名僅在與設定為 'both'reset_modules_order 結合使用時才有用。