2

I am trying to create a web application with Flask.

The problem is that it has been 2 weeks since I am stuck on a problem. I would like to run a python command that launches a server, retrieve the standard output, and display in real time on the web-site.

I do not know at all how to do because if I use "render_template" I do not see how to update the web site-the values sent in the console.

I use python 2.7, thank you very much

damien hoffmann
  • 29
  • 1
  • 1
  • 4
  • you should probably use something like ipython --notebook for this i would think ... – Joran Beasley Sep 15 '16 at 21:04
  • Real time data with flask ? Why apply all chain for streaming data ? Never will be gained a real time data. Start external thread+socket for streaming with related session. – dsgdfg Sep 15 '16 at 21:57

2 Answers2

1

It's gonna take a lot of work to get this done and probably more then you think but I'll still try to help you out.

To get any real time updates to the browser you're going to need something like a socket connection, something which allows you to send multiple messages at any time. Not just when the browser requests it.

So imagine this with a regular http connection you can only receive a message once and once you receive that message you cannot receive a message again. You can only call return once and not again.

Once you call return, you cannot call return again to send another message.

So basically with a regular http request you can only receive the log messages once and once any changes have been made to the log you cannot send those changes to the client again since the connection is end.

The connection is end the moment you call return.

There is a way to fix this by using a socket connection. A socket connection would allow you to open a connection with the user and server and they both can send messages at any time as long as the connection is open. The connection is only not open when you manually close it.

Check this answer for ways you could have real time updates with flask. If you want to do it with sockets (which is what I suggest you to use) then use the websocket interface instead.

There's options like socketio for python which allow you to write websocket applications in python.

Overall this is gonna be split into 5 parts:

  1. Start a websocket server when the Flask application start
  2. Create a javsacript file (one that the browser loads) that connects with the websocket server
  3. Find the function that gets triggered whenever Flask logging occurs
  4. Send a socket message with the log inside of it
  5. Make the browser display the log whenever it receives a websocket message

Here's a sample application written in Flask and socketio which should give you a idea on how to use socketio.

There's a lot to it and there's part you might be new to like websockets but don't let that stop you from doing what you want to do.

I hope this help, if any part confuses you then feel free to respond.

Community
  • 1
  • 1
user3254198
  • 763
  • 6
  • 23
1

The simple part : server side, you could redirect the stdout and stderr of the server to a file,

import sys

print("output will be redirected")
# stdout is saved
save_stdout = sys.stdout
fh = open("output.txt","w")
sys.stdout = fh

the server itself would then read that file within a subprocess.

f = subprocess.Popen(['tail','-F',"output.txt", '-n1'],\
                stdout=subprocess.PIPE,stderr=subprocess.PIPE)
p = select.poll()
p.register(f.stdout)

and the following threaded :

while True :
  if p.poll(1):
      output+=f.stdout.readline()

You can also use the tailhead or tailer libraries instead of the system tail

Now, the problem is that the standard output is a kind of active pipe and output is going to grow forever, so you'll need to keep only a frame of that output buffer.

If you have only one user that can connect to that window, the problem would be different, as you could flush the output as soon as is it send to that only client. See the difference between a terminal window and multiplexed, remote terminal window ?

I don't know flask, but client side, you only need some javascript to poll the server every second with an ajax request asking for the complete log (or --case of unique client-- the buffer to be appended to the DOM). You could also use websockets, but it's not an absolute necessity.

A compromise between the two is possible (infinite log with real time append / multiplexed at different rate) and it requires to keep a separate output buffer for each client.

Flint
  • 1,651
  • 1
  • 19
  • 29
  • 1
    Hi, what's select in select.poll() and what's output in output+=f.stdout.readline()? – Cibic Jan 03 '20 at 11:20
  • https://docs.python.org/3.8/library/select.html : Waiting for I/O completion. The `output` is self explanatory and outlined in the post – Flint Jan 04 '20 at 14:52