编写后端 -- pyplot 接口#

本页假设对 后端 页面中的信息有一般的了解,而是旨在作为第三方后端实现者的参考.它也只处理后端和 pyplot 之间的交互,而不是渲染方面,后者在 backend_template 中描述.

有两种用于定义后端的 API:一种是新的基于画布的 API(在 Matplotlib 3.6 中引入),另一种是较旧的基于函数的 API.新的 API 更容易实现,因为许多方法可以从"父后端"继承.如果对 Matplotlib < 3.6 的向后兼容性不是问题,建议使用它.但是,旧的 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 属性设置为所需的管理器类来定制 new_manager 的效果,并且(如果画布不能在管理器之前创建,如 wx 后端的情况一样)通过覆盖 FigureManager.create_with_canvas 类方法. (非交互式后端通常可以使用简单的 FigureManagerBase ,因此可以跳过此步骤.)

    在通过 pyplot.figure() 或通过反序列化在 pyplot 中注册一个新图形后,如果在交互模式下, 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 magic 命令使用,它必须与 BackendRegistry 支持的三种方式之一兼容:

内置#

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

module:// 语法#

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

入口点#

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

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

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