使用没有pyplot的Matplotlib

时间:2018-03-26 10:45:28

标签: python matplotlib

我正在尝试清理我们在该部分创建图表的库(python3 + matplotlib),其中一个噩梦是pyplot用法。

这个想法是让图形创建和渲染分割,避免使用pyplot。从理论上讲,步骤很简单:

  • 使用matplotlib.figure.Figure
  • 创建图形
  • 选择后端
  • 将它与画布相关联,如果后端具有GUI给管理员
  • 显示或保存到文件

所以我完成了以下工作的演示代码

#!/usr/bin/env python3

import sys
import importlib

import matplotlib
from matplotlib.figure import Figure


def fancy_plot():
    """
    Create a graph to render it in any canvas

    Returns:
        A Matplotlib Figure
    """
    fig = Figure()
    ax = fig.add_subplot(1, 1, 1)
    ax.plot([0, 1, 2, 3], [-1, 1, 0, 2])
    ax.set_title('Important graph')
    ax.grid(True)
    ax.set_xlabel('x')
    ax.set_ylabel('y')

    return fig


def select_backend(name=None):
    """
    Extracted from matplotlib.backends.__init__.py:pylab_setup

    Args:
        name: Name of the backend or None for the default one

    Returns:
        The backend module
    """
    # Import the requested backend into a generic module object
    if name is None:
        # validates, to match all_backends
        name = matplotlib.get_backend()
    if name.startswith('module://'):
        backend_name = name[9:]
    else:
        backend_name = 'backend_' + name
        backend_name = backend_name.lower()  # until we banish mixed case
        backend_name = 'matplotlib.backends.%s' % backend_name.lower()

    return importlib.import_module(backend_name)


def is_gui_backend(backend):
    """
    Check if the backend has a GUI or not.

    Args:
        backend: Module from matplotlib.backends.*

    Returns:
        True if the backend is in the list of matplotlib.rcsetup.interactive_bk
    """
    name = backend.__name__.lower()
    if '_' not in name:
        return False
    # Deal with the pesky capitalisation...
    interactive = [txt.lower() for txt in matplotlib.rcsetup.interactive_bk]

    return name.split('_')[-1] in interactive


def main():

    # Create a plot, not linked to any backend
    fig = fancy_plot()

    # Select the backend from command line
    if len(sys.argv) < 2:
        name = None
    else:
        name = sys.argv[1]

    # Now connect to the backend to effectively plot it
    backend = select_backend(name)

    if is_gui_backend(backend):
        print('Create Manager')
        # Use the machinery to create a canvas and a window to show it
        manager = backend.new_figure_manager_given_figure(1, fig)
        manager.show()
        backend.Show().mainloop()
    else:
        # Only the canvas is needed
        print('Just save to file')
        canvas = backend.FigureCanvas(fig)
        # This can be canvas.print_figure but savefig does a few more...
        fig.savefig('fancy')


if __name__ == '__main__':
    main()

但是有许多丑陋的方面。

要检测后端是否为gui,我会剪切模块名称并在rcsetup列表中搜索它。有没有更好的方法来检查这个?我正在考虑像hasattr(backend,'gui')

这样的东西

当后端是一个gui进入主循环时如果我只是backend.show()它会立即退出。 问题是在matplotlib.backend_bases._Backend.show中有代码:

managers = Gcf.get_all_fig_managers()
if not managers:
    return

这只显示了pyplot数字...好的,所以我需要访问_Backend.mainloop字段。 问题是,我发现访问的唯一方法是使用 backend.Show().mainloop()这似乎是一个反向兼容的代码片段,可能随时消失。

总结一下我的问题是:

  1. 这种做法是对的吗?

    编辑:对,我的意思是尝试使用matplotlib而不使用pyplot ... 在https://matplotlib.org/gallery/api/agg_oo_sgskip.html

  2. 的行中
  3. 有一种更好的方法可以看出后端是否与gui有关?
  4. 有更好的方法可以访问GUI主循环吗?
  5. 谢谢!

0 个答案:

没有答案