2

In my Flask application I have a similar loop, launched by a socket message emitted by the client:

@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

The question is: how can I stop/abort the loop from the client? I tried setting up an "abort" message, but it won't work. In other words, how can I use the <**condition**> I have drafted in the code?

2
  • Any luck with this? I'm looking pretty much for the same thing ;). Commented Nov 9, 2017 at 15:11
  • I am facing the same problem (need to be able to interrupt a while loop that emits messages to a client; and i need to interrupt it with another socket call). This example link uses a background thread to run such loop. So using multiple threads could be a solution. Commented Nov 23, 2017 at 2:26

1 Answer 1

8

Here is my implementation.

Server code:

#!/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)

Client code:

<!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>
Sign up to request clarification or add additional context in comments.

2 Comments

Hi @VilleLipponen Is it possible to continue the thread, after I call the stop method?
@bumbumpaw, I know this is a year later, but if you want to continue, just create another class function, where you set the switch to True. Then you can create another event, or just call it in the start.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.