2013-02-26 440 views
17

我希望能够访问一个网页,它将运行一个python函数并在网页上显示进度。如何在网页中持续显示Python输出?

因此,当您访问网页时,您可以看到脚本的输出,就像您从命令行运行它一样。基于

的答案在这里

How to continuously display python output in a webpage?

我试图从PYTHON

我试图用马库斯Unterwaditzer的代码与一个Python函数显示输出。

import flask 
import subprocess 

app = flask.Flask(__name__) 

def test(): 
    print "Test" 

@app.route('/yield') 
def index(): 
    def inner(): 
     proc = subprocess.Popen(
      test(), 
      shell=True, 
      stdout=subprocess.PIPE 
     ) 

     while proc.poll() is None: 
      yield proc.stdout.readline() + '<br/>\n' 
    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=5005) 

它运行,但我没有看到任何东西在浏览器中。

回答

20

你好像你不想调用一个测试函数,而是一个提供输出的实际命令行进程。还要从proc.stdout.readline或其他东西创建一个迭代器。你也从Python那里说过,我忘记了你应该只是在子进程中提取你想要的任何python代码,并把它放在一个单独的文件中。

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

哎呦,我改变了主机,所以它在我的流浪环境中工作。 – 2013-03-12 06:04:41

+0

OMG,我已经尝试了很多东西来得到这个工作,这是唯一做到的! – JeffThompson 2015-08-11 16:26:54

+0

如何将响应传递给模板中的特定点? – JeffThompson 2015-08-11 16:27:17

0

这里有一个解决方案,让您流子进程输出&负荷将静态地使用同一模板的事实后(假设你的子记录它自己的输出文件;如果没有,则记录过程输出到一个日志文件就留给读者做练习)

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()) 

这样你无论是在命令(通过POST)的初始运行和保存的静态服务过程中使用一致的模板事实之后的日志文件。