理解Flask中的 g 变量

Posted by Waynerv on

category: Web开发

Tags: Flask

全局变量

HTTP 是无状态的,因此 web 开发中一个很核心的问题是如何在不同请求间,以及一个请求的不同处理函数间传递数据,即传递参数。除了我们已经知道的cookie和session之外,Flask也提供了一些特别的对象用来处理该问题。

当仅在不同的处理函数间分享同一请求内有效的数据时,使用全局变量并不是一个好主意,因为它会在不同线程环境中中断。Flask为我们提供了一个特殊的对象 gg 只对当前活动的请求有效并且每个请求都会从中返回不同的值(ThreadLocal)。简单说,它的工作方式就像 Flask 中的 request 和 session一样。

flask.g 对象

g 对象是在一个应用上下文( application context ) 中可用来保存数据的命名空间对象(类似于 dict 字典)。它是 Flask.app_ctx_globals_class 也就是 ctx._AppCtxGlobals 类的一个实例。

g 可以用来在一个请求周期中保存资源。在测试时,你可以使用 Faking Resources and Context模式来提前配置这些资源。

它也是一个代理对象(proxy)。

flask.ctx._AppCtxGlobals 类

一个普通对象,用来作为在同一应用上下文中保存数据的命名空间 namespace。

创建应用上下文时将自动创建该对象,使用 g 作为代理对象来获取,g 保存的是当前请求的全局变量,不同的请求会有不同的全局变量,通过不同的thread id 进行区别。以下为该类所定义的方法:

  • 'key' in g

    检查属性是否存在。

  • iter(g)

    返回一个可遍历属性名称的迭代器。

  • get(name, default=None)

    通过 name 获取属性,如果属性不存在返回 default 值,就像 <code>dict.get()</code>.

    参数:

    • name – 要获取的属性名称.
    • default – 如果属性不存在时返回的值.
  • pop(name, default=)

    通过 name 获取并且删除属性. 就像 <code>dict.pop()</code>.

    参数:

    • name – 要弹出的属性名称.
    • default – 属性不存在时返回该值, 避免唤起 KeyError.
  • setdefault(name, default=None)

    通过 name 获取属性,若属性不存在则将其设为 default 值并返回该值. 就像 <code>dict.setdefault()</code>.

    参数:

    • name – 要获取的属性名称.
    • default - 若属性不存在将其设为该值并返回。

代理对象

一些 Flask 提供的对象是对其它对象的代理。每个工作线程(worker thread)以相同的方式访问代理对象,但指向的却是与每个工作线程绑定的唯一对象。

大部分时候我们不用关心这一点,但一些例外情况最好知道这些对象实际上只是作为代理:

  • 代理对象不能伪装成和真实对象相同的类型 type。如果你想要执行实例检查(即类型检查),你必须检查被代理的实际对象。
  • 当特定的对象引用非常重要时,如发送信号或传递数据到一个后台线程(开启多线程)。

如果需要获取被代理的实际对象,可以使用 <code>_get_current_object()</code> 方法:

app = current_app._get_current_object()
my_signal.send(app)

g 的生命周期

g 是基于每个应用上下文创建并且销毁的,而应用上下文 AppContext 又是随请求上下文 RequestContext 创建和销毁,因此我们可以说 g 是基于每个请求的,每个请求中的g对象不一样,每个 g 对象的生命周期就是当前请求的生命周期。

AppContext 内部封装 current_appg ,RequestContext内部封装 request 和 session ,AppContext 中均为本地代理对象,它的作用主要是帮助 request 获取当前的应用属性,它伴 request 而生,随 request 而灭。


注:转载本文,请与作者联系




如果觉得文章对您有价值,请作者喝杯咖啡吧

|
donate qrcode

欢迎通过微信与我联系

wechat qrcode

0 Comments latest

No comments.