2020

2

1

Flaskで簡易版プログレスバー実装して処理の進捗見れるようにしてやんよ!!!

Pocket
LINEで送る
Facebook にシェア
reddit にシェア
LinkedIn にシェア

機械学習などで何十万行のデータファイルをモデルに分析かける際に処理が完了するまで何十分〜時間とかかるので、GUIで簡易的にでも現在どれくらい処理が進んでいるかの状態を実装してみる

FlaskでWEBページを構築

まずは最低限の環境準備から
/progress
  ┗/templates/
    ┗index.html
┗app.py
上記のようなディレクトリを作成したらプログレスバーはBootstrapを使うのが一番手軽なので CSSとJSのCDNをここから取得

ビューファイル(/template/index.html)

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<!-- BootstrapのCDN(CSS)をここに -->
</head>
<body>
<div class="progress_wrap bg-dark m-5">
    <div class="progress-bar progress-bar-striped" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%">
        <span class="progress-bar-label mx-2">0%</span>
    </div>
</div>
<input type="button" id="ajax" class="btn btn-primary d-block mx-auto" value="処理開始">
<p id="result" class="text-center my-5"></p>

<!-- BootstrapのCDN(スクリプト)をここに -->
<script>
$(function(){
    var source = new EventSource("/stream");
    source.addEventListener('progress-item', function(event){
        $('.progress-bar').css('width', event.data + '%').attr('aria-valuenow', event.data);
        $('.progress-bar-label').text(event.data + '%');
    }, false);
    source.addEventListener('last-item', function(){
        source.close();
        $('.progress-bar').css('width', '100%').attr('aria-valuenow', 100);
        $('.progress-bar-label').text('100%');
    }, false);

    $("#ajax").click(function(){
        $.post('/ajax','data=処理開始', null,"json").done(function(data,textStatus,jqXHR) {
            const result = JSON.parse(data);
            console.log(result.data)
            $("#result").html('開始時間:'+ result.start + "<br>終了時間:" + result.end); 
        }).fail(function(jqXHR, textStatus, errorThrown ) {
            alert("処理失敗")
        });
    });
});
</script>
</body>
</html>
htmlファイルにCDNと上記コードを追記したらビュー部分はOK。
こういうビューが表示されます
BootstrapのCDNのjQueryはslim版でajaxメソッドは使えないため、サンプルをそのまままたはajaxメソッドを利用する場合は別途jQueryのCDNを利用してください

Flaskでバックエンド側を準備

次はコントローラー側を準備します。
from flask import Flask, Response, request, jsonify, render_template
from queue import Queue
import time
import datetime
import json

app = Flask(__name__)

# 進捗パーセンテージ用キュー
queue = Queue()

# プログレスバーストリーム
@app.route('/stream')
def stream():
    return Response(event_stream(queue), mimetype='text/event-stream')

# Queueの値を取り出してEventSourceの'progress-item'に出力(100だったら'last-item'イベントに出力)
def event_stream(queue):
    while True:
        persent = queue.get(True)
        print("progress:{}%".format(persent))
        sse_event = 'progress-item'
        if persent == 100:
            sse_event = 'last-item'
        yield "event:{event}\ndata:{data}\n\n".format(event=sse_event, data=persent)


# トップページ
@app.route("/")
def index():
    return render_template('index.html')


@app.route("/ajax", methods=['POST'])
def ajax():
    if request.method == 'POST':
        start = str(datetime.datetime.now())
        print("-------------- {} --------------".format(request.form['data']))
        """
        処理runner_01が終わったら10%まで進行としてキューに追加
        runner_01()
        queue.put(10)

        処理runner_02が終わったら20%まで進行としてキューに追加
        runner_02()
        queue.put(20)
        ・・・
        """

        # サンプル用ループ処理(2秒ごとに10パーセントづつ進行)
        for i in range(10,110,10):
            queue.put(i)
            time.sleep(3)

        end = str(datetime.datetime.now())
        result = {"start": start, "end": end }
        return jsonify(json.dumps(result))


if __name__ == '__main__':
    app.run(port=5000)

実行&確認

# Flaskを起動
$ python app.py
Flaskを立ち上げたら127.0.0.1:5000にアクセスするとビューページが表示されます。

「処理開始」ボタンをクリックすると3秒ごとに10パーセントづつ進行していきます。
(※ソースコードの処理内容によってはキューの反映がWEBページまで出力されずに飛ばし飛ばしで反映されます。)

動的な進捗反映システムではないですが、ワンライナーで書いたコードに
「今ここまで進んでるよー」の目安を差し込んでるので、
webアプリ上でも簡易的に進捗状況が目視確認できます。

Pocket
LINEで送る
Facebook にシェア
reddit にシェア
LinkedIn にシェア

トップへ