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.
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.
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".
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.
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.
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.
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