2016-12-25 71 views
1

我有一个功能,抓取网络的数据和计算搜索的分数。但是,这可能需要一段时间,有时在完成执行之前网页会超时。线程完成后,如何更改Flask中呈现的模板?

所以我创建了一个独立的线程来执行函数,loading.html告诉客户端数据仍在被收集。一旦该功能在线程中结束,如何重新加载网页以显示output.html,以显示分数。

这是我至今一个简单的版本:

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结束?

我想避免像redis这样的任务队列,因为我想部署这个应用程序在网络上,我不想招致费用(这是一个实验和业余爱好)。

与代码了详细的解答将有很大的帮助,因为我是新来的烧瓶中,多线程

回答

1

一个简单的方法是使循环Ajax请求到thread_status端点为您提供有关当前正在运行的任务信息。

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()要求:

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

您可以通过进度计数器,如果你喜欢,甚至追加此。但是你需要小心,防止线程多次运行。

+0

这工作就像我想要的一样!谢谢!不知道为什么我没有考虑过编写javascript函数 – Apara