JahMyst
JahMyst

Reputation: 1686

Flask + SocketIO - Stream command output to HTML element

I have a Flask Python webserver with websockets (socketIO).

I want to run a command and stream the output to a <p id='streaming_text'> HTML element.

This is my code:

HTML

div class='streaming'>
  <p id="streaming_text"></p>
</div>

JQuery

var socket = io.connect('http://' + document.domain + ':' + location.port + '/stream')

socket.on('message', function(msg){
  $('#streaming_text').append(msg);
})

...

jqxhr.done(function(cmd){
  socket.send(cmd)
  return false; 
})

Python

@socketio.on('message', namespace='/stream')
def stream(cmd):
    # Streams output of a command
    print("Received msg %s from JS socket" % cmd)
    print("Executing %s" % cmd)
    from shelljob import proc
    g = proc.Group()
    p = g.run(cmd)
    while g.is_pending():
        lines = g.readlines()
        for proc, line in lines:
            print(line)
            send(line, namespace='/stream')

In the browser console I see all the send(line) are executed at the same time: when the command finishes running. The print(line), however, shows me the output of my command in real-time.

The commands I run take in average 15 minutes to run, so it'd be a bad user experience to have to wait for that long without seeing any output.

How can I send those messages immediately without having to wait for the end of the command ?

Upvotes: 1

Views: 1730

Answers (1)

JahMyst
JahMyst

Reputation: 1686

To answer my own question, I solved this problem by adding: eventlet.sleep(0) after each send call in the Python code.

The new code is as such:

Python

@socketio.on('message', namespace='/stream') 
def stream(cmd):
   # Streams output of a command
   print("Received msg %s from JS socket" % cmd)
   print("Executing %s" % cmd)
   from shelljob import proc
   g = proc.Group()
   p = g.run(cmd)
   while g.is_pending():
       lines = g.readlines()
       for proc, line in lines:
           print(line)
           send(line, namespace='/stream')

Apparently this seems to flush the messages, so actually sends them right away to whatever code you're using to receive them, in my case a JavaScript (JQuery) script.

Source: https://github.com/miguelgrinberg/Flask-SocketIO/issues/141

Upvotes: 2

Related Questions