我正在尝试清理我们在该部分创建图表的库(python3 + matplotlib),其中一个噩梦是pyplot用法。
这个想法是让图形创建和渲染分割,避免使用pyplot。从理论上讲,步骤很简单:
所以我完成了以下工作的演示代码:
#!/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()
这似乎是一个反向兼容的代码片段,可能随时消失。
总结一下我的问题是:
这种做法是对的吗?
编辑:对,我的意思是尝试使用matplotlib而不使用pyplot ... 在https://matplotlib.org/gallery/api/agg_oo_sgskip.html
谢谢!