编写后端——pyplot 接口#

此页面假设一般了解 后端 页面中的信息,而作为第三方后端实现者的参考。它还仅处理后端与 pyplot 之间的交互,而不处理渲染方面,后者在 backend_template 中进行了描述。

定义后端的 API 有两种:一种是基于画布的新 API(在 Matplotlib 3.6 中引入),另一种是基于函数的旧 API。新 API 的实现更简单,因为许多方法可以从“父后端”继承。如果 Matplotlib < 3.6 的向后兼容性不是问题,则建议使用此 API。但是,旧 API 仍然受支持。

从根本上讲,后端模块需要向 pyplot 提供信息,以便

  1. pyplot.figure() 可以创建一个新的 Figure 实例,并将其与后端提供的画布类的实例相关联,该实例本身由后端提供的管理器类的实例托管。

  2. pyplot.show() 可以显示所有图形并启动 GUI 事件循环(如果有)。

为此,后端模块必须定义 FigureCanvasBasebackend_module.FigureCanvas 子类。在基于画布的 API 中,这是后端模块的唯一严格要求。基于函数的 API 还要求定义许多模块级函数。

基于画布的 API(Matplotlib >= 3.6)#

  1. 创建图形pyplot.figure() 调用 figure = Figure(); FigureCanvas.new_manager(figure, num)new_manager 是一个类方法)来实例化一个画布和一个管理器,并设置 figure.canvasfigure.canvas.manager 属性。图形解序列化使用相同的方法,但用解序列化的图形替换新实例化的 Figure()

    交互式后端应通过将 FigureCanvas.manager_class 属性设置为所需的管理器类,以及(如果画布不能在管理器之前创建,如 wx 后端的情况)通过覆盖 FigureManager.create_with_canvas 类方法来定制 new_manager 的效果。(非交互式后端通常可以使用一个简单的 FigureManagerBase,因此可以跳过此步骤。)

    在交互模式下,当使用 pyplot 注册新图形(通过 pyplot.figure() 或反序列化),pyplot 将调用其画布的 draw_idle() 方法,可根据需要覆盖此方法。

  2. 显示图形pyplot.show() 调用 FigureCanvas.manager_class.pyplot_show()(类方法),转发任何参数以启动主事件循环。

    默认情况下,pyplot_show() 检查是否向 pyplot 注册了任何 managers(如果没有则提前退出),对所有此类管理器调用 manager.show(),然后,如果使用 block=True(或使用默认的 block=None 且不在 IPython 的 pylab 模式中且不在交互模式中)调用,则调用 FigureCanvas.manager_class.start_main_loop()(类方法)以启动主事件循环。因此,交互式后端应相应地覆盖 FigureCanvas.manager_class.start_main_loop 类方法(或也可以直接覆盖 FigureCanvas.manager_class.pyplot_show)。

基于函数的 API#

  1. 创建图形pyplot.figure() 调用 new_figure_manager(num, *args, **kwargs)(它还负责创建新图形为 Figure(*args, **kwargs));反序列化调用 new_figure_manager_given_figure(num, figure)

    此外,在交互模式下,可以通过提供模块级 draw_if_interactive() 函数来自定义新注册图形的首次绘制。(在新基于画布的 API 中,此函数不再考虑。)

  2. 显示图形pyplot.show() 调用模块级 show() 函数,该函数通常通过 ShowBase 类及其 mainloop 方法生成。

注册后端#

对于可通过 matplotlib.use() 或 IPython %matplotlib 魔术命令使用的后端,它必须与 BackendRegistry 支持的三种方式之一兼容。

内置#

内置于 Matplotlib 的后端必须在 BackendRegistry 中硬编码其名称和 FigureCanvas.required_interactive_framework。如果后端模块不是 f"matplotlib.backends.backend_{backend_name.lower()}",则 BackendRegistry._name_to_module 中还必须有一个条目。

module:// 语法#

可以通过指定模块的路径(格式为 module://some.backend.module)来使用单独模块(未内置于 Matplotlib)中的任何后端。一个示例是 mplcairomodule://mplcairo.qt。后端的交互框架将从其 FigureCanvas.required_interactive_framework 中获取。

入口点#

外部后端模块可以使用 entry point 在其 pyproject.toml 中自注册为后端,例如 matplotlib-inline 使用的

[project.entry-points."matplotlib.backend"]
inline = "matplotlib_inline.backend_inline"

后端的交互式框架将从其 FigureCanvas.required_interactive_framework 中获取。所有入口点都会一起加载,但仅在首次需要时加载,例如当后端名称不被识别为内置后端时,或者当 list_all() 首次调用时。