Python Flaskアプリケーション内で新しいスレッドを開始しようとしています。リクエストによってトリガーされるバックグラウンド作業を行っていますが、そうではありません。リクエストに応答するために作業が完了するまで待つ必要があります。
このサブ脅威のflaskリクエストを着信したリクエストに設定することは可能ですか?理由は、DB(mongoDBの前のmongoengine)に対するクエリのACLはリクエストのユーザー(フラスコのリクエストオブジェクトから取得します)がオブジェクトにアクセスできるかどうかを確認し、サブスレッドでリクエストが利用できないために爆発します。
どんな考えでも大歓迎です。
以下は、現在どのように処理しているかを示す擬似コードですが、動作していません。
@app.route('/my_endpoint', methods=['POST'])
def my_endpoint_handler():
#do tracking in sub-thread so we don't hold up the page
def handle_sub_view(req):
from flask import request
request = req
# Do Expensive work
thread.start_new_thread(handle_sub_view, (request))
return "Thanks"
スレッドコードをtest_request_context
でラップして、 context locals にアクセスできるようにします。
@app.route('/my_endpoint', methods=['POST'])
def my_endpoint_handler():
#do tracking in sub-thread so we don't hold up the page
def handle_sub_view(req):
with app.test_request_context():
from flask import request
request = req
# Do Expensive work
thread.start_new_thread(handle_sub_view, (request))
return "Thanks"
Edit:スレッドが元のリクエストとは異なるコンテキストを持つことに注意する価値があります。スレッドを生成する前に、ユーザーIDなどの興味深いリクエストデータを抽出する必要があります。次に、IDを使用して、サブスレッドで(異なる)ユーザーオブジェクトを取得できます。
バージョン0.10以降、これを行うためのサポートされた方法があります。 http://flask.pocoo.org/docs/api/#flask.copy_current_request_context
_before_request
_フックを実行する場合は、装飾された関数内でcurrent_app.preprocess_request()
を呼び出す必要があります。
目的の情報をコピーして渡すことができます。
@app.route('/my_endpoint', methods=['POST'])
def my_endpoint_handler():
#do tracking in sub-thread so we don't hold up the page
def handle_sub_view(data):
# Use the data in subprocess
data = request.get_json() # copy the data
thread.start_new_thread(handle_sub_view, data)
return "Thanks"
@runfalkが指摘したように、 @copy_current_request_context
。動作するコードスニペットを次に示します。
import threading
from flask import request, jsonify, copy_current_request_context
@app.route('/foo')
def get_foo():
@copy_current_request_context
def foo_main():
# insert your code here
print(request.url)
threading.Thread(target=foo_main).start()
return jsonify({'status': 'started'})