How to continuously display Python output in a Webpage?

后端 未结 2 1453
花落未央
花落未央 2020-12-04 13:28

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

相关标签:
2条回答
  • 2020-12-04 14:00

    Hi looks like you don't want to call a test function, but an actual command line process which provides output. Also create an iterable from proc.stdout.readline or something. Also you said from Python which I forgot to include that you should just pull any python code you want in a subprocess and put it in a separate file.

    import flask
    import subprocess
    import time          #You don't need this. Just included it so you can see the output stream.
    
    app = flask.Flask(__name__)
    
    @app.route('/yield')
    def index():
        def inner():
            proc = subprocess.Popen(
                ['dmesg'],             #call something with a lot of output so we can see it
                shell=True,
                stdout=subprocess.PIPE
            )
    
            for line in iter(proc.stdout.readline,''):
                time.sleep(1)                           # Don't need this just shows the text streaming
                yield line.rstrip() + '<br/>\n'
    
        return flask.Response(inner(), mimetype='text/html')  # text/html is required for most browsers to show th$
    
    app.run(debug=True, port=5000, host='0.0.0.0')
    
    0 讨论(0)
  • 2020-12-04 14:18

    Here's a solution that allows you to stream the subprocess output & load it statically after the fact using the same template (assuming that your subprocess records it's own output to a file; if it doesn't, then recording the process output to a log file is left as an exercise for the reader)

    from flask import Response, escape
    from yourapp import app
    from subprocess import Popen, PIPE, STDOUT
    
    SENTINEL = '------------SPLIT----------HERE---------'
    VALID_ACTIONS = ('what', 'ever')
    
    def logview(logdata):
        """Render the template used for viewing logs."""
        # Probably a lot of other parameters here; this is simplified
        return render_template('logview.html', logdata=logdata)
    
    def stream(first, generator, last):
        """Preprocess output prior to streaming."""
        yield first
        for line in generator:
            yield escape(line.decode('utf-8'))  # Don't let subproc break our HTML
        yield last
    
    @app.route('/subprocess/<action>', methods=['POST'])
    def perform_action(action):
        """Call subprocess and stream output directly to clients."""
        if action not in VALID_ACTIONS:
            abort(400)
        first, _, last = logview(SENTINEL).partition(SENTINEL)
        path = '/path/to/your/script.py'
        proc = Popen((path,), stdout=PIPE, stderr=STDOUT)
        generator = stream(first, iter(proc.stdout.readline, b''), last)
        return Response(generator, mimetype='text/html')
    
    @app.route('/subprocess/<action>', methods=['GET'])
    def show_log(action):
        """Show one full log."""
        if action not in VALID_ACTIONS:
            abort(400)
        path = '/path/to/your/logfile'
        with open(path, encoding='utf-8') as data:
            return logview(logdata=data.read())
    

    This way you get a consistent template used both during the initial running of the command (via POST) and during static serving of the saved logfile after the fact.

    0 讨论(0)
提交回复
热议问题