2013-02-26 464 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)的初始運行和保存的靜態服務過程中使用一致的模板事實之後的日誌文件。