什么时候应该使用Flask.g?

时间:2013-02-26 07:49:46

标签: python flask

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

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

  • g位于请求上下文中,即在请求开始时重新创建,并且在请求结束时可用
  • g旨在用作“请求黑板”,我可以在请求期间放置相关内容(即,在请求开头设置一个标志并在最后处理它,可能来自before_request / after_request对)
  • 除持有请求级别状态外,g可以而且应该用于资源管理,即保存数据库连接等。

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

2 个答案:

答案 0 :(得分:92)

Advanced Flask Patternslinked by Markus,解释了0.10中对g的一些更改:

  • g现在位于应用程序环境中。
  • Every request pushes a new application context,擦除旧版本,因此g仍可用于为每个请求设置标记而无需更改代码。
  • 调用 teardown_request后,将弹出应用程序上下文。 (Armin的演讲解释了这是因为创建数据库连接之类的事情是设置请求的环境的任务,不应该在before_requestafter_request内处理

答案 1 :(得分:54)

作为本主题信息的附录:我对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所述,"每个请求都会推送一个新的应用程序上下文"。而as the Flask docs say,应用程序上下文"将不会在请求和#34;之间共享。现在,还没有明确说明(虽然我猜这些陈述暗示了这些),而我的测试清楚地表明,你应该从不明确地创建多个请求上下文嵌套在一个应用程序上下文中,因为flask.g(和co)没有任何魔法,因此它在两个不同的"级别中起作用。上下文,在申请和请求级别上独立存在不同的状态。

现实是"应用程序上下文"可能是一个误导性的名称,因为app.app_context() 每个请求的上下文,与"请求上下文"完全相同。可以将其视为一个"请求上下文精简版,仅在您需要一些通常需要请求上下文的变量的情况下才需要,但您不需要访问任何请求对象(例如在shell脚本中运行批处理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