Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use a flask session inside a python thread

How can I update a flask session inside a python thread? The below code is throwing this error:

*** RuntimeError: working outside of request context

from flask import session
def test(ses):
    ses['test'] = "test"

@app.route('/test', methods=['POST', 'GET'])
def mytest():
    t = threading.Thread(target=test, args=(session, ))
    t.start()
like image 901
alloyoussef Avatar asked Jul 10 '15 19:07

alloyoussef


People also ask

Is flask session thread safe?

Flask code has to be thread-safe, also called re-entrant. Local variables and parameters are always thread-safe. Instance variables, class variables, and global variables may not be thread-safe (but they might be). Nevertheless, threads and shared variables can be useful.

Is python Flask multi threaded?

As of Flask 1.0, flask server is multi-threaded by default. Each new request is handled in a new thread. This is a simple Flask application using default settings.

Does Flask support client side sessions?

Flask uses the client-side approach. Pros: Validating and creating sessions is fast (no data storage) Easy to scale (no need to replicate session data across web servers)


2 Answers

When you execute t.start(), you are creating an independent thread of execution which is not synchronized with the execution of the main thread in any way.

The Flask session object is only defined in the context of a particular HTTP request.

What does the variable session mean in the second thread (t)?

When t executes, there is no guarantee that the user request from the main thread still exists or is in a modifiable state. Perhaps the HTTP request has already been fully handled in the main thread.

Flask detects that you are trying to manipulate an object that is dependent on a particular context, and that your code is not running in that context. So it raises an exception.

There are a variety of approaches to synchronizing output from multiple threads into a single request context but... what are you actually trying to do here?

like image 76
Dan Lenski Avatar answered Sep 18 '22 15:09

Dan Lenski


None of the documentation I've seen really elaborates why this isn't possible in this framework - it's as if they have never heard of the use case.

In a nutshell, the built in session uses the user's browser (the cookie) as storage for the session - this is not what I understand sessions to be, and oh boy the security issues - don't store any secrets in there - the session is basically JSON encoded, compressed then set as a cookie - at least it's signed, I guess.

Flask-Session mitigates the security issues by behaving more like sessions do in other frameworks - the cookie is just an opaque identifier meaningful only in the back end - but the value changes every time the session changes, requiring the cookie be sent to the browser again - a background thread won't have access to the request when it's been completed a long time ago, so all you have is a one way transfer of data - out of the session and into your background task.

Might I suggest the baggage claim pattern? Your initial request handling function designates some key in some shared storage - a file on disk, a row in a database identified by some key, an object key in an in memory cache - whatever - and puts that in the session, then passes the session to your background process which can inspect the session for the location to place the results. Your subsequent request handling functions can then check this location for the results.

like image 37
Phil Avatar answered Sep 22 '22 15:09

Phil