Python HTML实时绘图

Mus*_*ger 6 html python data-visualization graph matplotlib

我正在尝试将一些实时数据可视化合并到我正在开发的Web应用程序中

我目前正在使用matplotlib和plotly。matplot的问题在于它不是基于Web的,而plotly的问题在于其具有流功能的实时绘图选项非常有限。

以下是我尝试创建的绘图类型的示例。所显示的只是静态的,但是由于我有实时数据,所以我想创建实时更新的相同类型的图表

在此处输入图片说明

数据是在SQL服务器中存储和更新的,因此我基本上只需要有一个脚本,该脚本将从SQL DB中获取最新值,然后每秒钟左右将其添加到图中。

什么是最好的(HTML兼容)解决方案?

您是否找到解决这个问题的方法?因为我遇到了同样的问题。我已经实现了动态图形绘图,可以使用matplotlib实时并连续刷新该图形。现在,我想在网页上绘制动态图,您有什么建议或例子吗?

QA *_*ive 3

有些评论包含值得一看的建议,这个Stack Overflow 问题也可能有用(尽管它不是 HTTP),而且您自己确实提到了plotly,它具有实时绘图功能

不过你提到你已经用 matplotlib 得到了你想要的图表。我也这样做了,所以编写了一些非常简单的代码来通过 HTTP 提供任意数量的图表,这也请求绘图的任何参数,其中之一是刷新周期。正如您从代码中可以看出的那样,它是为了临时诊断和监控(在我的情况下是机器学习进度)而故意最小化的。

用法:

  • 使用 python 3.6+(我经常使用f-strings )并将代码粘贴到文件中
  • 将绘图添加为 PlotRequestHandler 类下的方法(方法名称必须以 'plot_' 开头
  • 安装任何依赖项(plac + 绘图所需的任何其他库,例如我使用 pandas、matplotlib)
  • 通过双击(无参数)或命令行(带/不带参数)运行文件
  • 通过网络浏览器导航页面

代码:

import matplotlib.pyplot as plt
import pandas as pd
import io
from http.server import HTTPServer,BaseHTTPRequestHandler
import urllib
import inspect

class PlotRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        args = urllib.parse.parse_qs(self.path[2:])
        args = {i:args[i][0] for i in args}
        html = ''

        if 'mode' not in args:
            plots = ''
            for member in dir(self):
                if member[:5] == 'plot_':
                    plots += f'<a href="http://{self.server.server_name}:{self.server.server_port}/?mode=paramcheck&graph={member}">{member[5:].replace("_"," ").title()}</a><br/>\n'
            html = f'''<html><body><h1>Available Plots</h1>{plots}</body></html>'''

        elif args['mode'] == 'paramcheck':
            plotargs = inspect.getargspec(getattr(self,args['graph'])).args
            if len(plotargs) == 1 and plotargs[0].lower()=='self':
                args['mode'] = 'plotpage'
            else:
                for arg in plotargs:
                    if arg.lower() != 'self':
                        html += f"<input name='{arg}' placeholder='{arg}' value='' /><br />\n"
                html = f"<html><body><h1>Parameters:</h1><form method='GET'>{html}<input name='refresh_every' value='60' />(Refresh in sec)<br /><input type='hidden' name='mode' value='plotpage'/><input type='hidden' name='graph' value='{args['graph']}'/><input type='submit' value='Plot!'/></form></body></html>"

        elif args['mode'] == 'plotpage':
            html = f'''<html><head><meta http-equiv="refresh" content="{args['refresh_every']};URL=\'http://{self.server.server_name}:{self.server.server_port}{self.path}\'" /></head>
                       <body><img src="http://{self.server.server_name}:{self.server.server_port}{self.path.replace('plotpage','plot')}" /></body>'''

        elif args['mode'] == 'plot':
            try:
                plt = getattr(self,args['graph'])(*tuple((args[arg] for arg in inspect.getargspec(getattr(self,args['graph'])).args if arg in args)))
                self.send_response(200)
                self.send_header('Content-type', 'image/png')
                self.end_headers()
                plt.savefig(self.wfile, format='png')
            except Exception as e:
                html = f"<html><body><h1>Error:</h1>{e}</body></html>"

        if html != '':
            self.send_response(200)
            self.send_header('Content-type', 'text/html')
            self.end_headers()
            self.wfile.write(bytes(html,'utf-8'))

    def plot_convergence(self, file_path, sheet_name=None):
        if sheet_name == None:
            data = pd.read_csv(file_path)
        else:
            data = pd.read_excel(file_path, sheet_name)

        fig, ax1 = plt.subplots()

        ax1.set_xlabel('Iteration')
        ax1.set_ylabel('LOSS', color='tab:red')
        ax1.plot(data.iteration, data.loss, color='tab:red')

        ax2 = ax1.twinx()

        ax2.set_ylabel('Precision, Recall, f Score')
        ax2.plot(data.iteration, data.precision, color='tab:blue')
        ax2.plot(data.iteration, data.recall, color='tab:green')
        ax2.plot(data.iteration, data['f-score'], color='tab:orange')

        fig.tight_layout()
        plt.legend(loc=6)
        return plt


def main(server_port:"Port to serve on."=9999,server_address:"Local server name."=''):
    httpd = HTTPServer((server_address, server_port), PlotRequestHandler)
    print(f'Serving on http://{httpd.server_name}:{httpd.server_port} ...')
    httpd.serve_forever()


if __name__ == '__main__':
    import plac; plac.call(main)
Run Code Online (Sandbox Code Playgroud)