Writing a backend -- the pyplot interface#
This page assumes general understanding of the information in theBackends page, and is instead intended as reference forthird-party backend implementers. It also only deals with the interactionbetween backends andpyplot, not with the rendering side, which is describedinbackend_template.
There are two APIs for defining backends: a new canvas-based API (introduced inMatplotlib 3.6), and an older function-based API. The new API is simpler toimplement because many methods can be inherited from "parent backends". It isrecommended if back-compatibility for Matplotlib < 3.6 is not a concern.However, the old API remains supported.
Fundamentally, a backend module needs to provide information topyplot, sothat
pyplot.figure()can create a newFigureinstance and associate it withan instance of a backend-provided canvas class, itself hosted in an instanceof a backend-provided manager class.pyplot.show()can show all figures and start the GUI event loop (if any).
To do so, the backend module must define abackend_module.FigureCanvassubclass ofFigureCanvasBase. In the canvas-based API, this is the onlystrict requirement for backend modules. The function-based API additionallyrequires many module-level functions to be defined.
Canvas-based API (Matplotlib >= 3.6)#
Creating a figure:
pyplot.figure()callsfigure=Figure();FigureCanvas.new_manager(figure,num)(new_manageris a classmethod) to instantiate a canvas and a manager andset up thefigure.canvasandfigure.canvas.managerattributes.Figure unpickling uses the same approach, but replaces the newlyinstantiatedFigure()by the unpickled figure.Interactive backends should customize the effect of
new_managerbysetting theFigureCanvas.manager_classattribute to the desired managerclass, and additionally (if the canvas cannot be created before the manager,as in the case of the wx backends) by overriding theFigureManager.create_with_canvasclassmethod. (Non-interactive backendscan normally use a trivialFigureManagerBaseand can therefore skip thisstep.)After a new figure is registered with
pyplot(either viapyplot.figure()or via unpickling), if in interactive mode,pyplotwill call its canvas'draw_idle()method, which can be overridden asdesired.Showing figures:
pyplot.show()callsFigureCanvas.manager_class.pyplot_show()(a classmethod), forwarding anyarguments, to start the main event loop.By default,
pyplot_show()checks whether there are anymanagersregistered withpyplot(exiting early if not), callsmanager.show()on all such managers, and then, if called withblock=True(or withthe defaultblock=Noneand out of IPython's pylab mode and not ininteractive mode), callsFigureCanvas.manager_class.start_main_loop()(a classmethod) to start the main event loop. Interactive backends shouldtherefore override theFigureCanvas.manager_class.start_main_loopclassmethod accordingly (or alternatively, they may also directly overrideFigureCanvas.manager_class.pyplot_showdirectly).
Function-based API#
Creating a figure:
pyplot.figure()callsnew_figure_manager(num,*args,**kwargs)(which also takes care ofcreating the new figure asFigure(*args,**kwargs)); unpickling callsnew_figure_manager_given_figure(num,figure).Furthermore, in interactive mode, the first draw of the newly registeredfigure can be customized by providing a module-level
draw_if_interactive()function. (In the new canvas-based API, thisfunction is not taken into account anymore.)Showing figures:
pyplot.show()calls a module-levelshow()function, which is typically generated via theShowBaseclass and itsmainloopmethod.
Registering a backend#
For a new backend to be usable viamatplotlib.use() or IPython%matplotlib magic command, it must be compatible with one of the three wayssupported by theBackendRegistry:
Built-in#
A backend built into Matplotlib must have its name andFigureCanvas.required_interactive_framework hard-coded in theBackendRegistry. If the backend moduleis notf"matplotlib.backends.backend_{backend_name.lower()}" then theremust also be an entry in theBackendRegistry._name_to_module.
module:// syntax#
Any backend in a separate module (not built into Matplotlib) can be used byspecifying the path to the module in the formmodule://some.backend.module.An example ismodule://mplcairo.qt formplcairo. The backend'sinteractive framework will be taken from itsFigureCanvas.required_interactive_framework.
Entry point#
An external backend module can self-register as a backend using anentrypoint in itspyproject.toml such as the one used bymatplotlib-inline:
[project.entry-points."matplotlib.backend"]inline="matplotlib_inline.backend_inline"
The backend's interactive framework will be taken from itsFigureCanvas.required_interactive_framework. All entry points are loadedtogether but only when first needed, such as when a backend name is notrecognised as a built-in backend, or whenlist_all() is first called.