I am trying to start a new thread in Python inside of a Flask application. I am doing background work that gets triggered by the request, but I don't need to wait for the work to be done to respond to the request.
Is it possible to set the flask request in this sub-threat to the request that came in? Reason being, our ACL on our queries to our DB (mongoengine in front of mongoDB) relies on the request's user (it grabs it from flask's request object) to see if they have access to the objects, and its blowing up because the request is not available in the sub-thread.
Any thoughts would be much appreciated.
Here's pseudo code of how I am handling it now, but it is not working.
@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"
You should also be able to fix the following error: RuntimeError: Working outside of application context. This typically means that you attempted to use functionality that needed to interface with the current application object in some way. To solve this, set up an application context with app.
Flask automatically pushes a request context when handling a request. View functions, error handlers, and other functions that run during a request will have access to the request proxy, which points to the request object for the current request.
To start a Python Flask application in separate thread, we set the use_reloader to False when we call app. run . And then we create a Thread instance with the Flask app by setting the function that calls app. run as the value of the target argument.
The request context keeps track of the request-level data during a request. Rather than passing the request object to each function that runs during a request, the request and session proxies are accessed instead.
Wrap your thread code in a test_request_context
so you have access to 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: it's worth pointing out that the thread will have a different context than the original request. You need to extract any interesting request data, such as the user ID, before spawning the thread. You can then grab a (different) user object in the sub-thread using the ID.
Since version 0.10 there is a supported way of doing this: http://flask.pocoo.org/docs/api/#flask.copy_current_request_context
If you want the before_request
hooks to run you must call current_app.preprocess_request()
inside of the decorated function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With