Flask+Pyeharts前端实时动态展现多曲线多图实践

一:FLASK和Pyechats简介

        Flask是一个轻量级的可定制框架,使用Python语言编写,较其他同类型框架更为灵活、轻便、安全且容易上手。它可以很好地结合MVC模式进行开发,开发人员分工合作,小型团队在短时间内就可以完成功能丰富的中小型网站或Web服务的实现。另外,Flask还有很强的定制性,用户可以根据自己的需求来添加相应的功能,在保持核心功能简单的同时实现功能的丰富与扩展,其强大的插件库可以让用户实现个性化的网站定制,开发出功能强大的网站。

        Flask的基本模式为在程序里将一个视图函数分配给一个URL,每当用户访问这个URL时,系统就会执行给该URL分配好的视图函数,获取函数的返回值并将其显示到浏览器上,其工作过程见图。

Flask+Pyeharts前端实时动态展现多曲线多图实践_第1张图片

 

        Echarts 是一个由百度开源的数据可视化,凭借着良好的交互性,精巧的图表设计,得到了众多开发者的认可。而 Python 是一门富有表达力的语言,很适合用于数据处理。Pyecharts是对Echarts的Python封装。

        本实践基于pyechats官方网站提供的FLask+Pyechats框架,在框架里根据自己的需求来实现相关功能的实践。

        官网链接:https://pyecharts.org/#/zh-cn/web_flask

二:代码结构

 1,新建一个Flask目录

mkdir dpt_flask
cd dpt_flask
mkdir templates

2,拷贝pyechats模板

        将 pyecharts 模板,位于 pyecharts.render.templates 拷贝至刚新建的 templates 文件夹

        附上模板下载链接:https://github.com/pyecharts/pyecharts/

Flask+Pyeharts前端实时动态展现多曲线多图实践_第2张图片

 3,新建后端python代码文件app.py

        其总的代码结构如下:

.
├── app.py
├── static
│?? └── option.json
└── templates
    ├── index.html
    ├── macro
    ├── nb_jupyter_lab.html
    ├── nb_jupyter_notebook.html
    ├── nb_nteract.html
    ├── simple_chart.html
    └── simple_page.html

        关于static的文件夹及其文件作用,后面会讲到

三:功能实现

1,后端实现

        前端网页会定时从后端取数据进行动态实时显示,在具体实践中,数据是另外一个进程产生的,用zmq将数据从产生的地方传到本程序里(关于ZMQ的使用可查看我的另一篇博客https://blog.csdn.net/qq_27071221/article/details/119209941)。故单独起了一个线程去接收数据处理数据。具体代码如下:

头文件部分,主要是引入flask和pyechats的模块

import os
import zmq
import threading
from datetime import datetime
from flask.json import jsonify
from flask import Flask, render_template

from pyecharts import options as opts
from pyecharts.charts import Line
from pyecharts.globals import ThemeType

实例化Flask

app = Flask(__name__, static_folder="static",template_folder='templates')

Flask构造函数使用当前模块(__name __)的名称作为参数。

        我们这次要画的是曲线图(也可以说折线图),在后台实例化一个曲线图对象,并配置好相关参数,后面会将该配置好的曲线图参数传递到前端显示,该部分代码如下:

color = ['blue','cyan','green','red','darkorange','magenta','olive','black']

def line_base() -> Line:

    lineVol = Line(init_opts=opts.InitOpts(theme=ThemeType.SHINE))
    lineVol.add_xaxis([])
    for i in range(4):
        lineVol.add_yaxis(series_name="Thread"+str(i),y_axis=[],color=color[i],label_opts=opts.LabelOpts(is_show=False),)
    lineVol.set_global_opts(
            title_opts=opts.TitleOpts(title="XXXXX", pos_top="3%"),
            legend_opts=opts.LegendOpts(pos_top="5%"),
            toolbox_opts=opts.ToolboxOpts(is_show=True),
            tooltip_opts=opts.TooltipOpts(is_show=True, axis_pointer_type="cross", trigger="axis"),
            #datazoom_opts=opts.DataZoomOpts(type_="slider"),
            xaxis_opts=opts.AxisOpts(name='time'),
            yaxis_opts=opts.AxisOpts(type_='value',name='Volume',splitline_opts=opts.SplitLineOpts(is_show=True),is_scale=True),)

    return lineVol

        上面说过我们另外起了一个线程从另外一个进程取数据,这里面涉及到数据处理的部分,由于大家的数据需求不一样,故这里只给出一个框架,具体数据处理部分大家自己实现

def handleReciveData(reciveData):
    try:
        pass
    except:
        Pass

def getData():
    while True:
        print("*******************************************")
        pass

def receiveDataThread():
    dataThread1 = threading.Thread(target=getData)
    dataThread1.start()

接下来就是要实现前端和后端的交互实现

@app.route("/")
def index():
    return render_template("index.html")


@app.route("/lineChart")
def get_line_chart():
    c = line_base()
    return c.dump_options_with_quotes()

idx = 0
@app.route("/lineDynamicData1")
def update_line_data():
    if not timeList:
        return jsonify({"xTime": 0, "yValue": [0,0,0,0]})
    global idx
    idx = idx + 1
    if idx > len(timeList):
        idx = len(timeList)
return jsonify({"xTime": datetime.fromtimestamp(timeList[idx]).strftime("%H:%M:%S"), "yValue": volumeList[idx]})

Flask类的route()函数是一个装饰器,它告诉应用程序哪个URL应该调用相关的函数。

app.route(rule, options)
  • rule 参数表示与该函数的URL绑定。

  • options 是要转发给基础Rule对象的参数列表。

        在上面的示例中,'/ ' URL与index()函数绑定。因此,当在浏览器中打开web服务器的主页时,将呈现该函数的输出。

        对于@app.route("/lineChart"),当前端请求该URL的时候,会将上面配置好的曲线图进行实例化,然后c.dump_options_with_quotes()返回给前端显示。

        对于@app.route("/lineDynamicData1")就是每次前端调用的时候将要显示的具体数据传递给前端。

if __name__ == "__main__":
    receiveDataThread()
    app.run(host='192.168.46.84',port=5000,debug=False)

最后在主程序里,调用线程函数和app.run来运行起来后端应用程序

下面具体讲讲Flask的run方法

app.run(host, port, debug, options)

所有参数都是可选的

序号 参数与描述
1

host

要监听的主机名。 默认为127.0.0.1(localhost)。设置为“0.0.0.0”以使服务器在外部可用

2

port

默认值为5000

3

debug

默认为false。 如果设置为true,则提供调试信息

4

options

要转发到底层的Werkzeug服务器。

2,前端实现




    
    dpt-display
    
    
    
    
    
    


    

        这次需求是要展现的是三张图,由于篇幅以上给出了两张图的HTML,具体图的数量大家可以根据自己的需求去调整代码。下面具体讲讲我认为比较重要的地方。

        初始化一个Echats实例,配置渲染器,目前只支持'canvas'.width可显式指定实例宽度,单位为像素。如果传入值为 null/undefined/'auto',则表示自动取 dom(实例容器)的宽度。height可显式指定实例高度,单位为像素。如果传入值为 null/undefined/'auto',则表示自动取 dom(实例容器)的高度。'shine'是配置的主题

var chart = echarts.init(document.getElementById('Line'), 'shine', {renderer: 'canvas'});

init接口的定义如下:

(dom: HTMLDivElement|HTMLCanvasElement, theme?: Object|string, opts?: {
    devicePixelRatio?: number
    renderer?: string
    width?: number|string
    height? number|string
}) => ECharts

         fetchData()的url为"http://192.168.46.84:5000/lineChart"就是从后端的lineChart函数那里得到曲线图的配置json,然后用chart.setOption(result);设置好,此时前端就可以根据配置的参数进行曲线图的初步展示了。此时就有同学有疑问了,前端怎么根据url从后端拿数据呢,这就用到了ajax。

Flask+Pyeharts前端实时动态展现多曲线多图实践_第3张图片

Flask+Pyeharts前端实时动态展现多曲线多图实践_第4张图片

function fetchData() {
            $.ajax({
                type: "GET",
                url: "http://192.168.46.84:5000/lineChart",
                dataType: "json",
                success: function (result) {
                    chart.setOption(result);
                    for(var i=0;i<4;i++) 
                        old_data[i] = [];
                }
            });
        }

这里可以按F12查看我们前端设置的option是什么样子

Flask+Pyeharts前端实时动态展现多曲线多图实践_第5张图片

        那么怎么让图动起来呢,女主角来了

setInterval(getDynamicData1, 1000);

         该语句的作用就是1秒钟调用一次getDynamicData1方法,getDynamicData1方法同样利用ajax去后端取数据,将取到的数据塞到相应的data里,这样图就动起来了。

        需要注意的是这里面有一个坑,setInterval当我们电脑在正常运行没有锁屏或者休眠的情况下,的确是按照我们设置的1秒钟执行一次,但是假如我们电脑锁屏或者进入休眠状态后,有个现象是变成了1分钟执行一次,这是操作系统原因导致的。

        接下来我们只要依葫芦画瓢,在html里面再添加一个div块,就可以显示第二张图了。第二张图的设置里面,chart2.setOption(option);参数option是怎么来的呢

var chart2 = echarts.init(document.getElementById('Line2'), 'infographic', {renderer: 'canvas'});
        chart2.setOption(option);
        chart2.setOption({
                            title: [{text: "Pps of ZXDPI"}]
                        });
        chart2.setOption({
                            yAxis: [{name: "Packages"}]
                        });

上面讲到fetchData()的作用就是从后端拿到图标的配置数据,但是假如我们有现成的图标数据呢,这面的option就是我拷贝下来的第一张图的option,并且保存在static的文件夹下,其形式如下:

Flask+Pyeharts前端实时动态展现多曲线多图实践_第6张图片

 在html的head里引入该文件即可直接使用

 值得注意的是我们在填数据的时候会注意到往series里面填,因为官方例子也是只填了这地方,但实际上在个人开发中,还需要往xAxis的data里面填,这样显示才正常

"xAxis": [
        {
            "name": "time",
            "show": true,
            "scale": false,
            "nameLocation": "end",
            "nameGap": 15,
            "gridIndex": 0,
            "inverse": false,
            "offset": 0,
            "splitNumber": 5,
            "minInterval": 0,
            "splitLine": {
                "show": false,
                "lineStyle": {
                    "show": true,
                    "width": 1,
                    "opacity": 1,
                    "curveness": 0,
                    "type": "solid"
                }
            },
            "data": []
        }
    ],

四:曲线展示

         最后的效果就是一秒钟曲线动一次,由于某些原因不能给出动态图,抱歉,就看看静态的,想象它动起来的样子

Flask+Pyeharts前端实时动态展现多曲线多图实践_第7张图片

你可能感兴趣的:(Python,pyecharts,flask,实时,多图多曲线,python)