python socketio和Flask:如何在后台线程中停止循环?

时间:2017-06-05 14:17:40

标签: python-3.x flask socket.io

在我的Flask应用程序中,我有一个类似的循环,由客户端发出的套接字消息启动:

@socketio.on('start')
def my_start():
    global thread
    if thread is None:
        thread = socketio.start_background_task(target=background_thread)    

def background_thread():
        for i in range(1,100):
            socketio.emit('my_mess',{'data': i})
            if <**condition**>== True:
                socketio.emit('aborted')
                break
        if <**condition**> == False:
            socketio.emit('Success',{'data': '16.34 GB'})
        else:
            <**condition**> = False

问题是:如何从客户端停止/中止循环?我试过设置一个&#34; abort&#34;消息,但它不会起作用。换句话说,我如何使用我在代码中草拟的<**condition**>

1 个答案:

答案 0 :(得分:5)

这是我的实施。

服务器代码:

#!/usr/bin/env python

# make sure to use eventlet and call eventlet.monkey_patch()
import eventlet
eventlet.monkey_patch()

from flask import Flask, render_template, request, g, session, make_response, current_app, redirect, url_for
from flask_socketio import SocketIO, emit

app = Flask(__name__)
app.config['SECRET_KEY'] = "secret"

# make sure to set the async_mode as 'eventlet'
socketio = SocketIO(app, async_mode='eventlet')


# our gloabal worker
workerObject = None

class Worker(object):

    switch = False
    unit_of_work = 0

    def __init__(self, socketio):
        """
        assign socketio object to emit
        """
        self.socketio = socketio
        self.switch = True

    def do_work(self):
        """
        do work and emit message
        """

        while self.switch:
            self.unit_of_work += 1

            # must call emit from the socket io
            # must specify the namespace
            self.socketio.emit("update", {"msg": self.unit_of_work}, namespace="/work")

            # important to use eventlet's sleep method
            eventlet.sleep(1)

    def stop(self):
        """
        stop the loop
        """
        self.switch = False


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



@socketio.on('connect', namespace='/work')
def connect():
    """
    connect
    """

    global worker
    worker = Worker(socketio)
    emit("re_connect", {"msg": "connected"})


@socketio.on('start', namespace='/work')
def start_work():
    """
    trigger background thread
    """

    emit("update", {"msg": "starting worker"})

    # notice that the method is not called - don't put braces after method name
    socketio.start_background_task(target=worker.do_work)


@socketio.on('stop', namespace='/work')
def stop_work():
    """
    trigger background thread
    """

    worker.stop()
    emit("update", {"msg": "worker has been stoppped"})



if __name__ == '__main__':
    """
    launch server
    """
    socketio.run(app, host="0.0.0.0", port=5000, debug=True)

客户代码:

<!DOCTYPE HTML>
<html>
    <head>
        <title>Demo - background worker</title>

        <script type="text/javascript" src="http://code.jquery.com/jquery-latest.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" charset="utf-8">

            $(document).ready(function() {

                var socketio = null;
                var namespace = "/work"
                $("input[name='connect']").on("click", function() {

                    console.log("connect");

                    socketio = io.connect(
                            location.protocol       + 
                            '//'                    + 
                            document.domain         + 
                            ':'                     +    
                            location.port           + 
                            namespace               
                        );

                    socketio.off().on("re_connect", function(msg) {
                        $(".report").append(msg.msg + "<br />");
                    });
                });

                $("input[name='start']").on("click", function() {
                    socketio.emit("start");
                    socketio.on("update", function(msg) {
                        $(".report").append(msg.msg + "<br />");
                    });
                });

                $("input[name='stop']").on("click", function() {
                    socketio.emit("stop");
                    socketio.on("update", function(msg) {
                        $(".report").append(msg.msg + "<br />");
                    });
                });


            });

        </script>

    </head>

    <body>
        <div class="main_container" >

            <div class="control">

                <form id="ctrl_form">
                    <input type="button" name="connect" value="connect" />
                    <input type="button" name="start" value="start" />
                    <input type="button" name="stop" value="stop" />

                </form>
            </div>

            <div class="report">
                ...
            </div>
        </div>
    </body>
</html>