Monday 19 October 2020

Why child threads cannot access the current_user variable in flask_login?

I am writing a Flask application and I am trying to insert a multi-threaded implementation for certain server related features. I noticed this weird behavior so I wanted to understand why is it happening and how to solve it. I have the following code:

from flask_login import current_user, login_required
import threading

posts = Blueprint('posts', __name__)

@posts.route("/foo")
@login_required
def foo():
    print(current_user)
    thread = threading.Thread(target=goo)
    thread.start()
    thread.join()
    return


def goo():
    print(current_user)
    # ...

The main process correctly prints the current_user, while the child thread prints None.

User('Username1', 'email1@email.com', 'Username1-ProfilePic.jpg')
None

Why is it happening? How can I manage to obtain the current_user also in the child process? I tried passing it as argument of goo but I still get the same behavior.

I found this post but I can't understand how to ensure the context is not changing in this situation, so I tried providing a simpler example.

A partially working workaround

I tried passing as parameter also a newly created object User populated with the data from current_user

def foo():
    # ...
    user = User.query.filter_by(username=current_user.username).first_or_404()
    thread = threading.Thread(target=goo, args=[user])
    # ...

def goo(user):
    print(user)
    # ...

And it correctly prints the information of the current user. But since inside goo I am also performing database operations I get the following error:

RuntimeError: No application found. Either work inside a view function or push an application context. See http://flask-sqlalchemy.pocoo.org/contexts/.

So as I suspected I assume it's a problem of context.

I tried also inserting this inside goo as suggested by the error:

def goo():
    from myapp import create_app
    app = create_app()
    app.app_context().push()
    # ... database access

But I still get the same errors and if I try to print current_user I get None.

How can I pass the old context to the new thread? Or should I create a new one?



from Why child threads cannot access the current_user variable in flask_login?

No comments:

Post a Comment