71

我正在尝试在 Flask 应用程序内的 Python 中启动一个新线程。我正在做由请求触发的后台工作,但我不需要等待工作完成来响应请求。

是否可以将此子威胁中的烧瓶请求设置为传入的请求?原因是,我们对我们的数据库(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"
4

5 回答 5

78

将您的线程代码包装在 a 中test_request_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"

编辑:值得指出的是,线程将具有与原始请求不同的上下文。在生成线程之前,您需要提取任何有趣的请求数据,例如用户 ID。然后,您可以使用 ID 在子线程中获取(不同的)用户对象。

于 2012-03-29T19:32:24.273 回答
39

从 0.10 版开始,有一种支持的方式: http: //flask.pocoo.org/docs/api/#flask.copy_current_request_context

如果你想让before_request钩子运行,你必须current_app.preprocess_request()在装饰函数内部调用。

于 2013-07-11T13:25:48.400 回答
13

正如@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'})
于 2018-11-30T15:01:28.900 回答
5

您可以复制所需的信息并将其传递给:

@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"
于 2015-05-08T21:45:42.587 回答
1

更简洁的方法是使用包装应用程序上下文的 Flask 内置执行器,请参阅https://flask-executor.readthedocs.io/en/latest/

于 2020-08-18T02:15:27.550 回答