2016-12-25 3 views
1

私はウェブのデータをクロールして検索のスコアを計算する機能を持っています。ただし、これには時間がかかることがあり、実行を終了する前にウェブページがタイムアウトすることがあります。スレッドが完了したときにFlaskでレンダリングされたテンプレートを変更するにはどうすればよいですか?

したがって、私は関数を実行する別のスレッドを作成し、クライアントにデータがまだ収集されていることを伝えるloading.htmlを作成しました。関数がスレッドで終了すると、スコアを表示するoutput.htmlを表示するようにWebページを再ロードするにはどうすればいいですか?

これは私がこれまで持っているものの簡単なバージョンです:

from flask import Flask 
from flask import render_template 
from threading import Thread 

app = Flask(__name__) 

@app.route("/") 
def init(): 
    return render_template('index.html') 

@app.route("/", methods=['POST']) 
def load(): 
    th = Thread(target=something, args=()) 
    th.start() 
    return render_template('loading.html') 

def something(): 
    #do some calculation and return the needed value 

if __name__ == "__main__": 
    app.run() 

どうすればよいルートrender_template('output.html', x=score)に私のアプリのスレッド内のsomething()th終了すると?

私はこのアプリケーションをWebにデプロイしたいので、私はredisのようなタスクキューを避けようとしていますが、これは実験と趣味の多くです。私はフラスコかつ簡単な方法は、あなたの現在実行中のタスクに関する情報を提供します thread_statusエンドポイントへの巡回Ajaxリクエストを行っている

答えて

1

マルチスレッドに新しいですので、コードで

詳細な回答は大いに役立つだろう。あなたが好きならあなたも進行カウンターで、これを追加することができます

<html> 
    <head> 
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> 
    <script> 
     $(document).ready(function() { 
     var refresh_id = setInterval(function() { 
      $.get(
       "{{ url_for('thread_status') }}", 
       function(data) { 
       console.log(data); 
       if (data.status == 'finished') { 
        window.location.replace("{{ url_for('result') }}"); 
       } 
       } 
      )} 
      , 1000); 
     }); 
    </script> 
    </head> 
    <body> 
    <p>Loading...</p> 
    </body> 
</html> 

import time 
from flask import Flask, jsonify 
from flask import render_template 
from threading import Thread 

app = Flask(__name__) 
th = Thread() 
finished = False 


@app.route("/") 
def init(): 
    return render_template('index.html') 


@app.route("/", methods=['POST']) 
def load(): 
    global th 
    global finished 
    finished = False 
    th = Thread(target=something, args=()) 
    th.start() 
    return render_template('loading.html') 


def something(): 
    """ The worker function """ 
    global finished 
    time.sleep(5) 
    finished = True 


@app.route('/result') 
def result(): 
    """ Just give back the result of your heavy work """ 
    return 'Done' 


@app.route('/status') 
def thread_status(): 
    """ Return the status of the worker thread """ 
    return jsonify(dict(status=('finished' if finished else 'running'))) 


if __name__ == "__main__": 
    app.run(debug=True) 

は、だからあなた loading.htmlにだけ巡回アヤックス get()要求を挿入します。しかし、スレッドが複数回実行されないように注意する必要があります。

+0

これは私が望んでいたのと同じように機能します!ありがとう!なぜ私は前にjavascript関数を書くことを考えなかったのだろうか – Apara

関連する問題