How to continuously display python output in a webpage?

23,569

Solution 1

Here is a very simple app that streams a process' output with normal HTTP:

import flask
import time

app = flask.Flask(__name__)

@app.route('/yield')
def index():
    def inner():
        for x in range(100):
            time.sleep(1)
            yield '%s<br/>\n' % x
    return flask.Response(inner(), mimetype='text/html')  # text/html is required for most browsers to show the partial page immediately

app.run(debug=True)

Solution 2

I had the same problem today, and found a way to adapt Markus Unterwaditzer's answer to work with a template.

The key is to use jinja's Template.generate() instead of Template.render(), which is used by flask's render_template().

import flask
import time

from jinja2 import Environment
from jinja2.loaders import FileSystemLoader

app = flask.Flask(__name__)

@app.route('/yield')
def index():
    def inner():
        for x in range(100):
            time.sleep(1)
            yield '%s<br/>\n' % x
    env = Environment(loader=FileSystemLoader('templates'))
    tmpl = env.get_template('result.html')
    return flask.Response(tmpl.generate(result=inner()))

app.run(debug=True)

Assuming that there is a template result.html that looks like this:

{% extends "layout.html" %}
{% block body %}
<body>
  {% for line in result %}
    {{ line }}
  {% endfor %}
</body>
{% endblock %}

Solution 3

I would think the most straightforward way to do this is to create your page, and then use AJAX to make periodic requests to the server, and update the content on your page using the results. That might include implementing long polling to do this.

Any way you do this, you'll need to somehow make your function non-blocking, so that you can still serve requests while it operates. You could manually write a function that serves a request if there is one waiting and otherwise continues running the next "chunk" of the function. That would involve decomposing your function into small parts, so that you can dispatch them as needed.

A better approach might be to use threading or multiprocessing, depending on whether your function is bound by IO or CPU usage.

Solution 4

Do you have any plan to use WebSocket? if so, you can refer:Websocket with Flask and Gevent

Share:
23,569
Siecje
Author by

Siecje

Updated on June 28, 2020

Comments

  • Siecje
    Siecje almost 4 years

    I want to be able to visit a webpage and it will run a python function and display the progress in the webpage.

    So when you visit the webpage you can see the output of the script as if you ran it from the command line and see the output in the command line.

    What do I need to do in the function?

    What do I need to do in the template?

    EDIT:

    I am trying to use Markus Unterwaditzer's code with a template.

    {% extends "base.html" %}
    {% block content %}
    
    {% autoescape false %}
    
    {{word}}
    
    {% endautoescape %}
    
    {% endblock %}
    

    Python code

    import flask
    from flask import render_template
    import subprocess
    import time
    
    app = flask.Flask(__name__)
    
    @app.route('/yield')
    def index():
        def inner():
            for x in range(1000):
                yield '%s<br/>\n' % x
                time.sleep(1)
        return render_template('simple.html', word=inner())
        #return flask.Response(inner(), mimetype='text/html')  # text/html is required for most browsers to show the partial page immediately
    
    app.run(debug=True, port=8080)
    

    And it runs but I don't see anything in the browser.

  • Siecje
    Siecje about 11 years
    How can I use a python function?
  • Markus Unterwaditzer
    Markus Unterwaditzer about 11 years
    This actually might not be the best example, since it uses too much code that is unrelated to the question. I've updated it. Hope it's clearer now.
  • Siecje
    Siecje about 11 years
    Alright I added a delay and it continuously outputs to a webpage!! Great! I am trying to output it to a template that uses the same styling as the rest of my site but I don't see anything.
  • Marco L.
    Marco L. almost 11 years
    this works fine, but how to integrate these messages into a template?
  • NamPNQ
    NamPNQ over 7 years
    No need type text/html required. More info about stream context can be found in here: flask.pocoo.org/docs/0.11/patterns/streaming
  • Markus Unterwaditzer
    Markus Unterwaditzer over 7 years
    @NamPNQ Not required for streaming in general, but for a demo not every content-type will show immediate results in a browser.
  • S3DEV
    S3DEV over 5 years
    Can I up-vote this post 80 times?! I know this is discouraged, but THANK YOU!
  • scrollout
    scrollout about 3 years
    adding the env and tmpl variables to my code gives me jinja2.exceptions.UndefinedError: 'url_for' is undefined