微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Flask Socketio |使用 Flask Executor 或 ThreadPoolExecutor 创建的后台任务更新和绘制图表

如何解决Flask Socketio |使用 Flask Executor 或 ThreadPoolExecutor 创建的后台任务更新和绘制图表

我目前正在尝试在数据框的结果更新或数据发生任何变化时成功绘制条形图。

设置

  • Flask-SocketIO==4.3.1
  • python-engineio==3.13.2
  • python-socketio==4.6.0

确保重新启动机器以免遇到错误

Python 代码 - 保存在 D:\Projects\test_backgroundtask:

from flask import Flask,render_template,request
import pandas as pd
from flask_executor import Executor
import plotly
import plotly.graph_objs as go
from flask_socketio import SocketIO,emit
import json

global test_val
app = Flask(__name__)
socketio = SocketIO(app)
def create_plot(feature_importance):
    feature_importance=feature_importance.reset_index(drop=True)
    feature_importance=feature_importance.iloc[0:5]
    print(feature_importance)

    data = [
        go.Bar(
            x=feature_importance['Age'],# assign x as the dataframe column 'x'
            y=feature_importance['Name'],orientation='h'
        )
    ]

    graphJSON = json.dumps(data,cls=plotly.utils.PlotlyJSONEncoder)

    return graphJSON

@socketio.on("response")
def background_task_func():
    global test_val
    global plot
    socketio.sleep(10)
    data = {'Name': ['Tom','Joseph','Krish','John'],'Age': [20,21,19,18]}  
    test_val= pd.DataFrame(data)
    bar = create_plot(test_val)
    plot=bar
    if test_val.shape[0]>1:
        print(test_val)
        emit('response_output',plot,broadcast=True)
        socketio.sleep(1)
        #return render_template('views/index_img_soc.html',plot=bar)
    
@app.route('/',methods=['GET'])
def index():
    global plot
    executor.submit(background_task_func)
    bar = create_plot(test_val)
    
    return render_template('views/index_img_soc.html',plot=bar)



if __name__ == "__main__":
    data ={'Name': [],'Age': []}  
    test_val= pd.DataFrame(data)   
    executor = Executor(app)
    socketio.run(app) 

Html 代码(保存在 D:\Projects\test_backgroundtask\template\views):

<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script>
<div class="chart" id="bargraph">

    <script src="//cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js" integrity="sha256-yr4fRk/GU1ehYJPAs8P4JlTgu0Hdsp4ZKrx8bDEDC3I=" crossorigin="anonymous"></script>
        <script type="text/javascript" charset="utf-8">

            var socket = io().connect('http://127.0.0.1:5000');
            socket.emit('response')
            socket.on('response_output',function(receiving_data) {
              var graphs = {{plot | safe}};
              Plotly.plot('bargraph',graphs,{});
            });
    </script>
</div>

输出

WebSocket transport not available. Install eventlet or gevent and gevent-websocket for improved performance.
 * Serving Flask app "flask_background_app_img_soc2" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production Wsgi server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [14/Jul/2021 11:45:01] "GET / HTTP/1.1" 200 -
Empty DataFrame
Columns: [Name,Age]
Index: []
2c6e85bb23aa4c83af37bc005a08837b: Sending packet OPEN data {'sid': '2c6e85bb23aa4c83af37bc005a08837b','upgrades': [],'pingTimeout': 60000,'pingInterval': 25000}
2c6e85bb23aa4c83af37bc005a08837b: Sending packet MESSAGE data 0
127.0.0.1 - - [14/Jul/2021 11:45:03] "GET /socket.io/?EIO=3&transport=polling&t=NgaPyfS HTTP/1.1" 200 -
2c6e85bb23aa4c83af37bc005a08837b: Received packet MESSAGE data 2["response"]
received event "response" from 2c6e85bb23aa4c83af37bc005a08837b [/]
127.0.0.1 - - [14/Jul/2021 11:45:03] "POST /socket.io/?EIO=3&transport=polling&t=NgaPyf-&sid=2c6e85bb23aa4c83af37bc005a08837b HTTP/1.1" 200 -
     Name  Age
0     Tom   20
1  Joseph   21
2   Krish   19
3    John   18
     Name  Age
0     Tom   20
1  Joseph   21
2   Krish   19
3    John   18
emitting event "response_output" to all [/]
2c6e85bb23aa4c83af37bc005a08837b: Sending packet MESSAGE data 2["response_output","[{\"orientation\": \"h\",\"x\": [20,18],\"y\": [\"Tom\",\"Joseph\",\"Krish\",\"John\"],\"type\": \"bar\"}]"]
127.0.0.1 - - [14/Jul/2021 11:45:13] "GET /socket.io/?EIO=3&transport=polling&t=NgaPyg0&sid=2c6e85bb23aa4c83af37bc005a08837b HTTP/1.1" 200 -
     Name  Age
0     Tom   20
1  Joseph   21
2   Krish   19
3    John   18
     Name  Age
0     Tom   20
1  Joseph   21
2   Krish   19
3    John   18
2c6e85bb23aa4c83af37bc005a08837b: Received packet PING data None
2c6e85bb23aa4c83af37bc005a08837b: Sending packet PONG data None
127.0.0.1 - - [14/Jul/2021 11:45:28] "GET /socket.io/?EIO=3&transport=polling&t=NgaP_9E&sid=2c6e85bb23aa4c83af37bc005a08837b HTTP/1.1" 200 -
127.0.0.1 - - [14/Jul/2021 11:45:28] "POST /socket.io/?EIO=3&transport=polling&t=NgaQ2md&sid=2c6e85bb23aa4c83af37bc005a08837b HTTP/1.1" 200 -
2c6e85bb23aa4c83af37bc005a08837b: Received packet PING data None
2c6e85bb23aa4c83af37bc005a08837b: Sending packet PONG data None
127.0.0.1 - - [14/Jul/2021 11:45:54] "GET /socket.io/?EIO=3&transport=polling&t=NgaQ2nA&sid=2c6e85bb23aa4c83af37bc005a08837b HTTP/1.1" 200 -
127.0.0.1 - - [14/Jul/2021 11:45:54] "POST /socket.io/?EIO=3&transport=polling&t=NgaQ93n&sid=2c6e85bb23aa4c83af37bc005a08837b HTTP/1.1" 200 -
2c6e85bb23aa4c83af37bc005a08837b: Received packet PING data None
2c6e85bb23aa4c83af37bc005a08837b: Sending packet PONG data None
127.0.0.1 - - [14/Jul/2021 11:46:20] "GET /socket.io/?EIO=3&transport=polling&t=NgaQ94a&sid=2c6e85bb23aa4c83af37bc005a08837b HTTP/1.1" 200 -
127.0.0.1 - - [14/Jul/2021 11:46:20] "POST /socket.io/?EIO=3&transport=polling&t=NgaQFPv&sid=2c6e85bb23aa4c83af37bc005a08837b HTTP/1.1" 200 -

一个输出,即使数据帧已更新。

first output

重新加载页面后,页面为空白,然后显示正确的图表。

after reload

我想要达到的目标

  1. 更新数据框时自动显示条形图无需重新加载页面

解决方法

在 html 页面的 function(receiving_data) 中,使用变量 plot 代替 receiving_data。变量 plot 在调用 render_template 时被初始化。通过套接字发送数据时,调用 return plot 时不需要传递变量 render_template('views/index_img_soc.html',plot=bar)

请参阅下面的示例脚本,了解如何使用套接字将数据发送到 html 脚本。

下面的脚本会在不重新加载页面的情况下自动更新条形图。

使用chart.js 而不是plotly 的代码。在 javascript 中绘制 chart.js 而不是 plotly 的例子要多得多。

更新的 Python 脚本:

import random
from flask import Flask,render_template,session,request
from flask_socketio import SocketIO
from flask_executor import Executor
import pandas as pd
import json
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)
thread = None



@socketio.on("response_demo")
def background_task_func():
    """Example of how to send server generated events to clients."""

    socketio.sleep(5)
    print("send")
   
    data = {'Name': ['Tom','Joseph','Krish','John','Shadz'],'Age': [20,21,19,18,36]} 

    data_2= pd.DataFrame(data)
    
    df_json=data_2.to_json(orient='records')
    result = {"objects": json.loads(df_json)}
    socketio.emit('my_response',result,broadcast=True)

@app.route('/')
def index():
    executor.submit(background_task_func)
    return render_template('index_2.html')



if __name__ == '__main__':
    executor = Executor(app)
    socketio.run(app)

更新的 html 脚本:

<!DOCTYPE HTML>
<html>
<head>
    <title>Flask-SocketIO Test</title>
    <script type="text/javascript" src="//code.jquery.com/jquery-1.4.2.min.js"></script>
    <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.5/socket.io.min.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js" integrity="sha256-yr4fRk/GU1ehYJPAs8P4JlTgu0Hdsp4ZKrx8bDEDC3I=" crossorigin="anonymous"></script>

</head>

<canvas id="myChart" width="100" height="100"></canvas>
    <script type="text/javascript" charset="utf-8">

// Chart.js Bar Chart
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx,{
    type: 'bar',data: {
        labels: ["Red","Blue","Yellow","Green","Purple"],datasets: [{
            data: [2,2,2],backgroundColor: [
                'rgba(255,99,132,0.2)','rgba(54,162,235,'rgba(255,206,86,'rgba(75,192,'rgba(153,102,255,0.2)'
            ],borderColor: [
                'rgba(255,1)',1)'
            ],borderWidth: 1
        }]
    },options: {
        scales: {
 
            yAxes: [{
                ticks: {
                    beginAtZero:true
                }
            }]
        }
    }
});


        $(document).ready(function() {

            var socket = io().connect('http://127.0.0.1:5000');
            socket.emit('response_demo')
            socket.on('my_response',function(obj) {
            for (var i=0; i < obj.objects.length; i++) {
             myChart.data.datasets[0].data[i] =obj.objects[i].Age;
             myChart.data.labels[i] =obj.objects[i].Name;
            
            }
            
                myChart.update();
           
            });

        });

</script>
</html>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?