问题:什么时候应使用Flask.g?
我锯是g
将请求上下文移动到应用程序上下文瓶0.10,这让我感到困惑的预期用途g
。
我的理解(对于Flask 0.9)是:
g
驻留在请求上下文中,即在请求开始时重新创建,直到结束时可用g
旨在用作“请求黑板”,在这里我可以放置与请求持续时间相关的内容(即,在请求的开始处设置一个标志,并在结束时(可能从before_request
/after_request
对开始)进行处理)- 除了保持请求级别状态外,
g
还可以并且应该用于资源管理,即保持数据库连接等。
在Flask 0.10中,以下哪句话不再适用?有人可以指点我讨论这种变化原因的资源吗?在Flask 0.10中,我应该将什么用作“请求黑板”?我应该创建自己的应用程序/扩展特定于线程的本地代理并将其推送到上下文堆栈before_request
吗?如果我的应用程序生存时间很长(不像请求),因此资源从未被释放,那么在应用程序上下文中资源管理的意义何在?
回答 0
g
现在位于应用程序上下文中。- 每个请求都会推送一个新的应用程序上下文,从而清除旧的应用程序上下文,因此
g
仍可以用于按请求设置标志,而无需更改代码。 - 调用后 弹出应用程序上下文
teardown_request
。(Armin的演示文稿解释了这是因为创建数据库连接之类的事情是为请求设置环境的任务,不应在before_request
和中处理after_request
)
回答 1
作为该线程中信息的附录:我也flask.g
对它的行为感到困惑,但是一些快速测试帮助我弄清了它。这是我尝试过的方法:
from flask import Flask, g
app = Flask(__name__)
with app.app_context():
print('in app context, before first request context')
print('setting g.foo to abc')
g.foo = 'abc'
print('g.foo should be abc, is: {0}'.format(g.foo))
with app.test_request_context():
print('in first request context')
print('g.foo should be abc, is: {0}'.format(g.foo))
print('setting g.foo to xyz')
g.foo = 'xyz'
print('g.foo should be xyz, is: {0}'.format(g.foo))
print('in app context, after first request context')
print('g.foo should be abc, is: {0}'.format(g.foo))
with app.test_request_context():
print('in second request context')
print('g.foo should be abc, is: {0}'.format(g.foo))
print('setting g.foo to pqr')
g.foo = 'pqr'
print('g.foo should be pqr, is: {0}'.format(g.foo))
print('in app context, after second request context')
print('g.foo should be abc, is: {0}'.format(g.foo))
这是它提供的输出:
in app context, before first request context
setting g.foo to abc
g.foo should be abc, is: abc
in first request context
g.foo should be abc, is: abc
setting g.foo to xyz
g.foo should be xyz, is: xyz
in app context, after first request context
g.foo should be abc, is: xyz
in second request context
g.foo should be abc, is: xyz
setting g.foo to pqr
g.foo should be pqr, is: pqr
in app context, after second request context
g.foo should be abc, is: pqr
正如Y4Kman所说的那样,“每个请求都推送一个新的应用程序上下文”。而随着烧瓶文档说,应用程序上下文“将不被请求之间共享”。现在,尚未明确说明的内容(尽管我猜想这是这些语句的隐含内容),而我的测试清楚地表明,您永远不应明确创建嵌套在一个应用程序上下文中的多个请求上下文,因为flask.g
(和co)没有它具有任何神奇的功能,使其可以在上下文的两个不同“级别”中起作用,并且在应用程序和请求级别独立存在不同的状态。
现实情况是,“应用程序上下文”可能app.app_context()
是一个颇具误导性的名称,因为它是每个请求上下文,与“请求上下文”完全相同。将其视为“请求上下文精简版”,仅在需要一些通常需要请求上下文的变量但不需要访问任何请求对象的情况下才需要(例如,在数据库中运行批处理DB操作时)外壳脚本)。如果您尝试将应用程序上下文扩展为包含多个请求上下文,那么您将遇到麻烦。因此,您应该在Flask的上下文中编写如下代码,而不是上面的测试:
from flask import Flask, g
app = Flask(__name__)
with app.app_context():
print('in app context, before first request context')
print('setting g.foo to abc')
g.foo = 'abc'
print('g.foo should be abc, is: {0}'.format(g.foo))
with app.test_request_context():
print('in first request context')
print('g.foo should be None, is: {0}'.format(g.get('foo')))
print('setting g.foo to xyz')
g.foo = 'xyz'
print('g.foo should be xyz, is: {0}'.format(g.foo))
with app.test_request_context():
print('in second request context')
print('g.foo should be None, is: {0}'.format(g.get('foo')))
print('setting g.foo to pqr')
g.foo = 'pqr'
print('g.foo should be pqr, is: {0}'.format(g.foo))
这将产生预期的结果:
in app context, before first request context
setting g.foo to abc
g.foo should be abc, is: abc
in first request context
g.foo should be None, is: None
setting g.foo to xyz
g.foo should be xyz, is: xyz
in second request context
g.foo should be None, is: None
setting g.foo to pqr
g.foo should be pqr, is: pqr