本記事の背景
以前はFlaskで時間がかかる処理で同期でやってしまっていたが、本記事は非同期処理を紹介する
Processの使用
Pythonで非同期のやり方はいろいろありますが、本記事はマルチスレッドのProcessを使うやり方を紹介する
※公式ページの解説は以下です。
The Process class¶
In multiprocessing, processes are spawned by creating a Process object and then calling its start() method. Process follows the API of threading.Thread. A trivial example of a multiprocess program is
from multiprocessing import Process
def f(name):
print('hello', name)
if __name__ == '__main__':
p = Process(target=f, args=('bob',))
p.start()
p.join()
FlaskでProcessを使用
FlaskでProcessを使用する場合は上記のソースをすこし工夫します。
@app.route('/download', methods=['POST'])
def async_download():
# グローバル変数を宣言
global thread
form = DownloadForm()
if request.method =="POST":
url = request.form.get("url")
tp = request.form.get("tp")
file_name = request.form.get('file_name')
if tp == 'mp3' and len(url) > 1:
thread = Process(target=download_mp3, args=(url,file_name))
# プロセスをスタートする(thread.join()は実行しない)
thread.start()
elif tp == 'mp4' and len(url) > 1:
thread = Process(target=download_mp4, args=(url,file_name))
thread.start()
else:
return render_template('index.html', form=form)
# ダウンロード中のページを表示させる
return render_template('download.html')
制限事項
ダウンロード中のページの表示
※ ダウンロードのプロセスについて
Flaskのフロント側は静的ページ表示しているため、同期処理の動きと異なる。
また、ダウンロード終わっても、ページの遷移はありません。
ただし、ダウンロードモジュールにフック関数を実装して、DBに保存するようなものだったり、Jsonファイルに完了フラグを付けるなりして、別の監視プロセスを走らせることでメッセージの通知を実装すれば、ダウンロード終わったら、Lineにメッセージを通知することも可能です。
それについては、別途で記事にする予定。
参考文献