Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access flask.g inside greenlet

I'm using Flask + gevent and want to access the flask.g application global inside the target function of a greenlet. I'm using the copy_current_request_context decorator and have a situation pretty similar to example given in the docs:

import gevent
from flask import copy_current_request_context, g

@app.route('/')
def index():
    g.user_data = 'foobar'
    g.more_user_data = 'baz'

    @copy_current_request_context
    def do_some_work():
        some_func(g.user_data, g.more_user_data)
        ...  

    gevent.spawn(do_some_work)
    return 'Regular response'

However, I get the following error:

AttributeError: '_AppCtxGlobals' object has no attribute 'user_data'

I think a new application context is pushed when the request context is copied? I set a trace in the Flask code here and that seems to be the case. So the error isn't all that surprising because the flask.g object is application context scoped as of 0.10 (see http://flask.pocoo.org/docs/0.12/api/#flask.Flask.app_ctx_globals_class).

Obviously, I can just pass the user data into the target function as arguments:

import gevent
from flask import g

@app.route('/')
def index():
    g.user_data = 'foobar'
    g.more_user_data = 'baz'

    def do_some_work(user_data, more_user_data):
        some_func(user_data, more_user_data)
        ...  

    gevent.spawn(do_some_work, g.user_data, g.more_user_data)
    return 'Regular response'

And this works just fine, but I was hoping to use flask.g if possible.

like image 338
jamesdarabi Avatar asked Nov 20 '17 03:11

jamesdarabi


People also ask

What is the use of G in flask?

g is an object for storing data during the application context of a running Flask web app. g can also be imported directly from the flask module instead of flask.globals, so you will often see that shortcut in example code.

What is the Greenlet package?

The greenlet package is a spin-off of Stackless, a version of CPython that supports micro-threads called "tasklets". Tasklets run pseudo-concurrently (typically in a single or a few OS-level threads) and are synchronized with data exchanges on "channels".

What is flask-WTF?

Flask-WTF ( project documentation and PyPI page ) provides a bridge between Flask and the the WTForms form-handling library. It makes it easier to use WTForms by reducing boilerplate code and shorter examples for common form operations as well as common security practices such as CSRF.

What is the flask starter app?

tedivm's flask starter app is a base of Flask code and related projects such as Celery which provides a template to start your own Flask web app. The project comes baked with an admin panel, API authentication and authorization , SQLAlchemy and many other common libraries that are often used with Flask.


1 Answers

flask.g is bound with the app context, not on request context, as the doc says:

Starting with Flask 0.10 this is stored on the application context and no longer on the request context ...

copy_current_request_context() only copy request context, but give you a new app context. You could create one to pass current app context with closure:

def copy_current_app_context(f):
    from flask.globals import _app_ctx_stack
    appctx = _app_ctx_stack.top
    def _(*args, **kwargs):
        with appctx:
            return f(*args, **kwargs)
    return _

However, I prefer pass data to greenlet explicitly via arguments, which is cleaner.

like image 119
georgexsh Avatar answered Oct 19 '22 13:10

georgexsh