Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flask throwing 'working outside of request context' when starting sub thread

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" 
like image 770
MattoTodd Avatar asked Mar 29 '12 19:03

MattoTodd


People also ask

How do I fix RuntimeError working outside of request context?

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.

How can a request context be created in flask Python?

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.

How do I run a flask in a separate thread?

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.

What is request context in Python?

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.


2 Answers

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.

like image 149
Alex Morega Avatar answered Sep 19 '22 06:09

Alex Morega


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.

like image 44
runfalk Avatar answered Sep 19 '22 06:09

runfalk