弗拉斯克什么时候应该。G被使用?

看到,在Flask 0.10中,g将从请求上下文移动到应用程序上下文,这使我对g的预期用途感到困惑。

我的理解(对于Flask 0.9)是:

  • g存在于请求上下文中,也就是说,在请求开始时重新创建,并且直到它结束都可用
  • g打算用作“请求黑板”,在那里我可以放置与请求持续时间相关的东西(即,在请求的开始设置一个标志,并在结束时处理它,可能来自before_request/after_request对)
  • 除了保存请求级状态外,g还可以而且应该用于资源管理,即保存数据库连接等。

下面哪个句子在Flask 0.10中不再正确了?有人能给我指出一个资源讨论原因的变化吗?我应该在Flask 0.10中使用什么作为“请求黑板”-我是否应该创建自己的应用程序/扩展特定的线程本地代理并将其推到上下文堆栈before_request?如果我的应用程序存在很长一段时间(不像请求),因此资源永远不会被释放,那么在应用程序上下文中进行资源管理的意义是什么?

119403 次浏览

高级烧瓶图案,作为链接:Markus,解释了0.10中g的一些变化:

  • g现在存在于应用程序上下文中。
  • 每个请求都会推送一个新的应用程序上下文,擦除旧的,所以g仍然可以用来设置每个请求的标志,而不需要更改代码。
  • 应用程序上下文弹出 teardown_request被调用。(Armin的演示解释了这是因为像创建DB连接这样的任务在请求的环境中设置,不应该在before_requestafter_request中处理)

作为本线程中信息的补充:我对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

正如他们4kman上面所说的,“每个请求都会推动一个新的应用程序上下文”。而正如弗拉斯克医生所说,应用程序上下文“不会在请求之间共享”。现在,没有显式说明的是(尽管我猜这是从这些语句中暗示出来的),而我的测试清楚地表明,你应该从来没有显式地创建嵌套在一个应用程序上下文中的多个请求上下文,因为flask.g(和co)没有任何魔力,它在两个不同的上下文中发挥作用,在应用程序和请求级别上独立存在不同的状态。

实际情况是“应用程序上下文”可能是一个相当容易误导人的名称,因为app.app_context() a 每个请求上下文,与“请求上下文”完全相同。可以把它看作是“请求上下文简化版”,只有当你需要一些通常需要请求上下文的变量时才需要,但你不需要访问任何请求对象(例如,在shell脚本中运行批处理DB操作时)。如果您试图扩展应用程序上下文以包含多个请求上下文,那么您就是在自找麻烦。所以,比起我上面的测试,你应该用Flask的context编写如下代码:

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