Вызывание колбы «работа вне контекста запроса» при запуске подпотока - PullRequest
48 голосов
/ 29 марта 2012

Я пытаюсь начать новый поток в Python внутри приложения Flask.Я выполняю фоновую работу, которая запускается запросом, но мне не нужно ждать, пока будет выполнена работа, чтобы ответить на запрос.

Возможно ли установить запрос колбы в этом разделе?угроза запроса, который пришел?Причина в том, что наш ACL в наших запросах к нашей БД (mongoengine перед mongoDB) полагается на пользователя запроса (он берет его из объекта запроса фляги), чтобы увидеть, есть ли у него доступ к объектам, и его взрыв, потому что запроснедоступно в подпотоке.

Любые мысли будут высоко оценены.

Вот псевдокод того, как я обращаюсь с ним сейчас, но он не работает.

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

Ответы [ 4 ]

59 голосов
/ 29 марта 2012

Оберните код вашего потока в test_request_context, чтобы у вас был доступ к локальным контекстам :

@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 : стоит указать, что потокбудет иметь другой контекст, чем исходный запрос.Вам нужно извлечь любые интересные данные запроса, такие как идентификатор пользователя, перед тем как создать поток.Затем вы можете получить (другой) пользовательский объект в подпотоке, используя идентификатор.

30 голосов
/ 11 июля 2013

Начиная с версии 0.10 существует поддерживаемый способ сделать это: http://flask.pocoo.org/docs/api/#flask.copy_current_request_context

Если вы хотите, чтобы хуки before_request запускались, вы должны вызвать current_app.preprocess_request() внутри оформленной функции.

5 голосов
/ 09 мая 2015

Вы можете скопировать необходимую информацию и передать ее:

@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"
1 голос
/ 30 ноября 2018

Как отметил @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'})
...