Доступ к флажке.
Я использую Flask + gevent и хочу получить доступ к приложению flask.g
в пределах целевой функции гриля.
Я использую декоратор copy_current_request_context
и имеет ситуацию, очень похожую на пример, приведенный в документах:
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'
Однако я получаю следующую ошибку:
AttributeError: '_AppCtxGlobals' object has no attribute 'user_data'
Я думаю, что новый контекст приложения толкается при копировании контекста запроса? Я установил трассировку в флеш-код здесь, и это похоже на случай. Таким образом, ошибка не так уж и удивительна, потому что объект flask.g
- это контекст приложения с областью действия 0.10 (см. http://flask.pocoo.org/docs/0.12/api/#flask.Flask.app_ctx_globals_class).
Очевидно, что я могу просто передать пользовательские данные в целевую функцию в качестве аргументов:
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'
И это работает отлично, но я надеялся использовать flask.g
, если это возможно.
Ответы
Ответ 1
flask.g
привязан к контексту приложения, а не по запросу, как говорит doc:
Начиная с Flask 0.10, это сохраняется в контексте приложения и больше не находится в контексте запроса...
copy_current_request_context()
только контекст запроса копирования, но дает вам новый контекст приложения. Вы можете создать его для передачи текущего контекста приложения с закрытием:
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 _
Однако я предпочитаю передавать данные в greenlet явно через аргументы, которые являются более чистыми.