摘要:matplotlib
结合seaborn
二维绘图功能强大,可以绘制eCharts
画不出的图像,因此考虑直接将matplotlib
图像渲染到前端。
文章说明
文章说明:前端绘图一般是用百度eCharts
,但其样式不够丰富且可定制化程度不高,有时无法满足需求,因此直接将python
的matplotlib
数据可视化渲染到前端。
另请参考:python
将matplotlib
输出到web
另请参考:如何将Matplotlib
图像展示在web页面上
另请参考:Mac使用matplotlib.pyplot
画图出现中文乱码
文章作者:鴻塵
文章链接:https://hwame.top/20201008/render-matplotlib-figure-to-flaskweb.html
一、背景
前端页面的数据可视化一般是用百度eCharts
,但其样式不够丰富且可定制化程度不高,有时无法满足需求。
最近需要在前端展示相关图(Correlogram),python
中可以使用matplotlib
结合seaborn
轻松实现,但eCharts实例中没有类似的样例,因此考虑直接将matplotlib
图像渲染到前端。
二、思路
1.保存图片到服务器static
目录
将画好的图片保存在服务器的static
目录下,前端再从该目录读取图片进行展示。这种思路很直接,是最容易想到的,但是存在以下问题:
- 无法判断响应时间。因为图像生成是通过前端用户传递一系列参数,再根据这些参数计算相应的数据,利用计算的数据进行可视化,因此后端生成图片的时间未知,所以只能采用在前端延时展示。
- 前端访问
static
目录不方便。前端VUE
+后端Flask
的前后端分离的项目中,前端访问static
目录不方便。 - 占用服务器内存和带宽。将图片保存在服务器,前端从服务器获取资源时会占用一部分网络带宽,影响到前端资源加载的速度,并且图片累积将会占用服务器内存。
2.使用请求的方式将图像传到前端
将图像以请求的方式传到前端,前端只需将<img>
标签的src
属性赋值为后端的请求路径即可。
该方法可以在后端生成完图像后再发送给前端,无需设置延时获取图像。拟采用该方法。
3.将图像以Base64
格式发送给前端
这种思路和思路2类似,但是区别在于调用savefig
方法时不存储为图像,而是存储为二进制格式,二进制格式再转化为Base64
字符串格式,并将其发送给前端,前端只需要将<img>
标签的src
属性赋值为该字符串即可。
三、代码实现
对比三种方法,显然思路3为最优解:
- 在后端生成完图像后再发送给前端,无需设置延时获取图像;
- 只需要往前端发送一次请求,代码更加精简;
- 调用了 savefig 方法,可以去除白边。
接口使用python
的flask
框架,代码如下:
1 | import matplotlib |
四、效果预览
前端通过请求获取该src
后,只需将其赋值给<img>
标签的src
属性即可:
1 | <img src={{src}}> |
预览图如下:

五、部署问题
1.无GUI图形界面
服务器是不带GUI界面的CentOS 7
,但是matplotlib.pyplot
是需要tkinter
库的支持的:_tkinter.TclError: no display name and no $DISPLAY environment variable
。
然而,我们并不需要安装tkinter
、tcl-devel
和tk-devel
等,因为我们并不是需要在Linux
上看到画出的图,只需要改一下后端agg
即可【貌似Linux
下默认后端已是Agg
,从配置文件可以看到】,代码如下:
1 | import matplotlib as mpl |
2.中文字体乱码
原因分析
由于matplotlib
没有中文字体,直接会报错:RuntimeWarning: Glyph xxxxx missing from current font.
,网上有说需要添加两行代码(在缺少字体文件的情况下,这种方法无效),即:
1 | plt.rcParams['font.sans-serif'] = ['SimHei'] |
因为没有黑体这个字体,所以仍会报错,因此需要手动下载对应字体。并将其复制到对应位置:./python3.6/site-packages/matplotlib/mpl-data/fonts/ttf/
。
修改配置文件
解决字体缺失的问题后,还需要修改配置文件matplotlibrc
,文件位置:./python3.6/site-packages/matplotlib/mpl-data/matplotlibrc
。直接修改配置文件的好处是,不需要每次都在程序代码中添加诸如plt.rcParams['font.sans-serif'] = ['SimHei']
的配置项。
- 将
#font.family : sans-serif
修改为font.family : sans-serif
(去掉注释) - 将
#font.sans-serif : DejaVu Serif, ...
修改为font.sans-serif : SimHei, DejaVu Serif, ...
(去掉注释,添加SimHei
) - 将
#axes.unicode_minus : True
修改为axes.unicode_minus : False
(去掉注释,属性设置为False
)
说明:黑体SimHei
也可以改为其他字体,最接近宋体和Times New Roman的是STSong
,参考如何使matplotlib同时使用宋体和Times New Roman。
删除matplotlib
缓存
Linux
上的matplotlib
缓存文件位于用户家目录下的”~/.cache/matplotlib/“,可以看到其下包含了缓存文件fontlist-v310.json
及缓存文件夹tex.cache
。若不删除缓存,可能看不到配置生效。
1 | rm -rf ~/.cache/matplotlib/ |
3.其他
任何人都没法保证自己写的代码没有bug,而且测试时也不可能考虑到所有的情况。一旦程序部署上线作为服务运行,出现问题用户也只能看到50x
的错误,因此要养成善于查看日志的习惯!从日志入手,才能分析问题出现的原因,从而能打补丁、修bug、改代码,使程序更健壮、服务更稳定。
Preview: