Backend schreiben -- die pyplot-Schnittstelle#

Diese Seite setzt ein allgemeines Verständnis der Informationen auf der Seite Backends voraus und dient stattdessen als Referenz für Implementierer von Drittanbieter-Backends. Sie behandelt auch nur die Interaktion zwischen Backends und pyplot, nicht die Rendering-Seite, die in backend_template beschrieben wird.

Es gibt zwei APIs zur Definition von Backends: eine neue Canvas-basierte API (eingeführt in Matplotlib 3.6) und eine ältere Funktions-basierte API. Die neue API ist einfacher zu implementieren, da viele Methoden von "Eltern-Backends" geerbt werden können. Sie wird empfohlen, wenn die Rückwärtskompatibilität für Matplotlib < 3.6 keine Rolle spielt. Die alte API bleibt jedoch weiterhin unterstützt.

Grundsätzlich muss ein Backend-Modul Informationen für pyplot bereitstellen, damit

  1. pyplot.figure() eine neue Figure-Instanz erstellen und diese mit einer Instanz einer vom Backend bereitgestellten Canvas-Klasse verknüpfen kann, die selbst in einer Instanz einer vom Backend bereitgestellten Manager-Klasse gehostet wird.

  2. pyplot.show() kann alle Figuren anzeigen und die GUI-Ereignisschleife starten (falls vorhanden).

Dazu muss das Backend-Modul eine backend_module.FigureCanvas-Unterklasse von FigureCanvasBase definieren. In der Canvas-basierten API ist dies die einzige zwingende Anforderung für Backend-Module. Die Funktions-basierte API erfordert zusätzlich die Definition vieler Funktionen auf Modulebene.

Canvas-basierte API (Matplotlib >= 3.6)#

  1. Figur erstellen: pyplot.figure() ruft figure = Figure(); FigureCanvas.new_manager(figure, num) (eine Klassenmethode) auf, um eine Canvas und einen Manager zu instanziieren und die Attribute figure.canvas und figure.canvas.manager einzurichten. Das Entpickeln von Figuren verwendet den gleichen Ansatz, ersetzt aber die neu instanziierte Figure() durch die entpickelte Figur.

    Interaktive Backends sollten die Auswirkung von new_manager anpassen, indem sie das Attribut FigureCanvas.manager_class auf die gewünschte Manager-Klasse setzen und zusätzlich (falls die Canvas nicht vor dem Manager erstellt werden kann, wie bei wx-Backends) die Klassenmethode FigureManager.create_with_canvas überschreiben. (Nicht-interaktive Backends können normalerweise ein triviales FigureManagerBase verwenden und können diesen Schritt daher überspringen.)

    Nachdem eine neue Figur bei pyplot registriert wurde (entweder über pyplot.figure() oder über Entpickeln), ruft pyplot im interaktiven Modus die Methode draw_idle() der Canvas auf, die nach Wunsch überschrieben werden kann.

  2. Figuren anzeigen: pyplot.show() ruft die Klassenmethode FigureCanvas.manager_class.pyplot_show() auf und übergibt alle Argumente, um die Haupt-Ereignisschleife zu starten.

    Standardmäßig prüft pyplot_show(), ob bei pyplot irgendwelche manager registriert sind (und beendet frühzeitig, falls nicht), ruft manager.show() für alle solchen Manager auf und ruft dann, wenn mit block=True (oder mit dem Standard block=None und außerhalb des IPython-pylab-Modus und nicht im interaktiven Modus) aufgerufen, die Klassenmethode FigureCanvas.manager_class.start_main_loop() auf, um die Haupt-Ereignisschleife zu starten. Interaktive Backends sollten daher die Klassenmethode FigureCanvas.manager_class.start_main_loop entsprechend überschreiben (oder alternativ können sie auch direkt FigureCanvas.manager_class.pyplot_show überschreiben).

Funktions-basierte API#

  1. Figur erstellen: pyplot.figure() ruft new_figure_manager(num, *args, **kwargs) auf (die sich auch um die Erstellung der neuen Figur als Figure(*args, **kwargs) kümmert); das Entpickeln ruft new_figure_manager_given_figure(num, figure) auf.

    Darüber hinaus kann im interaktiven Modus die erste Darstellung der neu registrierten Figur durch Angabe einer Funktion draw_if_interactive() auf Modulebene angepasst werden. (In der neuen Canvas-basierten API wird diese Funktion nicht mehr berücksichtigt.)

  2. Figuren anzeigen: pyplot.show() ruft eine Funktion show() auf Modulebene auf, die typischerweise über die Klasse ShowBase und ihre Methode mainloop generiert wird.

Ein Backend registrieren#

Damit ein neues Backend über matplotlib.use() oder den IPython %matplotlib Magic-Befehl verwendet werden kann, muss es mit einer der drei von BackendRegistry unterstützten Arten kompatibel sein.

Integriert#

Ein in Matplotlib integriertes Backend muss seinen Namen und FigureCanvas.required_interactive_framework fest in der BackendRegistry kodiert haben. Wenn das Backend-Modul nicht f"matplotlib.backends.backend_{backend_name.lower()}" ist, muss es auch einen Eintrag in BackendRegistry._name_to_module geben.

module:// Syntax#

Jedes Backend in einem separaten Modul (nicht in Matplotlib integriert) kann verwendet werden, indem der Pfad zum Modul in der Form module://some.backend.module angegeben wird. Ein Beispiel ist module://mplcairo.qt für mplcairo. Das interaktive Framework des Backends wird von seinem FigureCanvas.required_interactive_framework übernommen.

Einstiegspunkt#

Ein externes Backend-Modul kann sich selbst als Backend registrieren, indem es einen entry point in seiner pyproject.toml verwendet, wie z. B. bei matplotlib-inline

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

Das interaktive Framework des Backends wird von seinem FigureCanvas.required_interactive_framework übernommen. Alle Einstiegspunkte werden zusammen geladen, aber erst bei Bedarf, z. B. wenn ein Backend-Name nicht als integriertes Backend erkannt wird oder wenn list_all() zum ersten Mal aufgerufen wird.