繁体   English   中英

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

[英]When should Flask.g be used?

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

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

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

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

由 Markus 链接的Advanced Flask Patterns解释了 0.10 中g一些更改:

  • g现在存在于应用程序上下文中。
  • 每个请求都会推送一个新的应用程序上下文,擦除旧的应用程序上下文,因此g仍可用于为每个请求设置标志,而无需更改代码。
  • 调用teardown_request弹出应用程序上下文。 (Armin 的演讲解释了这是因为创建数据库连接之类的事情是为请求设置环境的任务,不应在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

正如Y4Kman 上面所说,“每个请求都会推送一个新的应用程序上下文”。 正如 Flask 文档所说,应用程序上下文“不会在请求之间共享”。 现在,还没有明确说明(尽管我猜这些陈述暗示了这一点),并且我的测试清楚地表明,您永远不应该显式地创建嵌套在一个应用程序上下文中的多个请求上下文,因为flask.g (和 co ) 没有任何神奇之处,它可以在两个不同的上下文“级别”中运行,不同的状态独立存在于应用程序和请求级别。

现实情况是,“应用程序上下文”可能是一个具有误导性的名称,因为app.app_context()每个请求的上下文,与“请求上下文”完全相同。 将其视为“请求上下文精简版”,仅在您需要一些通常需要请求上下文的变量的情况下才需要,但您不需要访问任何请求对象(例如,在运行批处理数据库操作时外壳脚本)。 如果您尝试扩展应用程序上下文以包含多个请求上下文,那么您就是在自找麻烦。 因此,您应该使用 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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM