2016-12-25 1 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와 같은 작업 대기열을 피하려고합니다. 내가 플라스크하고 쉬운 방법은 당신에게 현재 실행중인 작업에 대한 정보를 제공하는 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

이것은 내가 원했던 것처럼 작동합니다! 감사! 왜 내가 전에 자바 스크립트 함수를 작성하지 않았는지 궁금 – Apara

관련 문제