如何通过烧瓶应用程序流式传输数据?

Posted

技术标签:

【中文标题】如何通过烧瓶应用程序流式传输数据?【英文标题】:How do I stream data through a flask application? 【发布时间】:2017-05-17 13:19:15 【问题描述】:

我正在研究使用 Flask 应用程序作为嵌入式系统接口的可能性。我以前使用过烧瓶(例如,我编写了一些非常基本的烧瓶站点来轮询外部系统以响应页面加载以填充图表),但我不确定如何将数据推送到 Flask 应用程序并在用户的浏览器上。

我计划使用 ZeroMQ 将数据从在嵌入式设备上运行的 C++ 应用程序推送到烧瓶应用程序(也在嵌入式设备上运行)。

根据我的阅读,flask-socketIO 之类的内容可能会将内容从 Flask 获取到用户的浏览器。

我不清楚的一件事是是否有可能/您将如何从 ZeroMQ 接收数据并将其推送到浏览器?

【问题讨论】:

如果使用后台线程是正确的方法,可能与another SO post 重复? 我已经使用 websockets 和 gevent 完成了它,并且效果很好。可以在这里查看我的示例:github.com/reptillicus/zmq/blob/master/exmaples/diffusion/… 主要只是客户端与服务器端版本略有变化并破坏一切的令人沮丧的问题。我放弃了 另外,现在几乎所有东西都支持标准的 web sockets,所以真的不需要 socketio @reptilicus - 我试了一下你的建议,但是 wsgi 服务器在加载请求时似乎抛出了错误(参见上面的编辑)。 【参考方案1】:

如果其他人也想做同样的事情,这是我可以根据 reptilicus 的示例归结为最简单的示例...

说明

    在下面提到的结构中设置下面的代码。 安装下面列出的 Python 模块 运行服务器 运行数据源 打开网络浏览器并导航到http://localhost:25000/

如果一切正常,您应该会看到一个非常基本的页面:

Python / 模块

这些是我的测试实现使用的版本。其他人也可以工作。

Python v3.5.2 Pyzmq v15.2.0 gevent v1.2.0 karellen-geventws v1.0.1(需要 gevent-websocket 以支持 Python 3) Flask v0.10.1 Flask-Sockets v0.2.1

您还需要一份Reconnecting Websocket 的副本,可用here。

代码布局

\ZmqFlaskForwarder
    \static
        \js
            application.js
            reconnecting-websocket.min.js
    \templates
        index.html
    data_source.py
    server.py

服务器应用程序(server.py)

import zmq.green as zmq
import json
import gevent
from flask_sockets import Sockets
from flask import Flask, render_template
import logging
from gevent import monkey

monkey.patch_all()

app = Flask(__name__)
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

sockets = Sockets(app)
context = zmq.Context()

ZMQ_LISTENING_PORT = 12000

@app.route('/')
def index():
    logger.info('Rendering index page')
    return render_template('index.html')

@sockets.route('/zeromq')
def send_data(ws):
    logger.info('Got a websocket connection, sending up data from zmq')
    socket = context.socket(zmq.SUB)
    socket.connect('tcp://localhost:PORT'.format(PORT=ZMQ_LISTENING_PORT))
    socket.setsockopt_string(zmq.SUBSCRIBE, "")
    poller = zmq.Poller()
    poller.register(socket, zmq.POLLIN)
    gevent.sleep()
    received = 0
    while True:
        received += 1
        # socks = dict(poller.poll())
        # if socket in socks and socks[socket] == zmq.POLLIN:
        data = socket.recv_json()
        logger.info(str(received)+str(data))
        ws.send(json.dumps(data))
        gevent.sleep()

if __name__ == '__main__':
    logger.info('Launching web server')
    from gevent import pywsgi
    from geventwebsocket.handler import WebSocketHandler
    server = pywsgi.WSGIServer(('', 25000), app, handler_class=WebSocketHandler)
    logger.info('Starting serving')
    server.serve_forever()

数据源(data_source.py)

import zmq
import random
import sys
import time
import json

port = "12000"

context = zmq.Context()
socket = context.socket(zmq.PUB)
socket.bind("tcp://*:%s" % port)
while True:
    first_data_element = random.randrange(2,20)
    second_data_element = random.randrange(0,360)
    message = json.dumps('First Data':first_data_element, 'Second Data':second_data_element)
    print(message)
    socket.send_string(message)
    time.sleep(0.5)

客户端 javascript (application.js)

ws = new ReconnectingWebSocket("ws://"  + location.host + '/zeromq')

ws.onmessage = function(message) 
  payload = JSON.parse(message.data);
  $('#latest_data').html('<h2> Data: ' + message.data + '</h2>');
;

模板(index.html)

<!DOCTYPE html>
<html>
  <head>
    <title>Python Websockets ZeroMQ demo</title>
  </head>
  <body>
    <div class="container">
      <h2> Simple ZeroMQ data streaming via web sockets! </h2>
      <div id="latest_data"></div>
    </div>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
    <script type="text/javascript" src="static/js/reconnecting-websocket.min.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.6/d3.min.js"></script>
    <script type="text/javascript" src="static/js/application.js"></script>
  </body>
</html>

【讨论】:

这是我找了一段时间的东西。谢谢。在一台 PC 上它是完美的,另一台 - 当我关闭页面时,它显示错误 geventwebsocket.exceptions.WebSocketError: Socket is dead ..dist-packages/geventwebsocket/websocket.py 但另一个电脑是完美的。谢谢

以上是关于如何通过烧瓶应用程序流式传输数据?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Jinja 进行 Flask 模板流式传输

如何将音频数据从 Android 流式传输到 WebSocket 服务器?

如何通过 PHP api 在 Flutter 中流式传输 MySQL 数据库记录?

通过 Spring JDBC 流式传输数据,长度未知

如何流式传输(大)日志文件?

如何将我的数据从 supabase 流式传输到颤振应用程序