Flask一个g引发的思考

本文从一次面试经历出发,探讨了Flask框架中全局变量g的实现原理。通过对Flask源码的阅读,详细分析了LocalProxy如何作为代理访问AppContext中的g属性。文中介绍了LocalProxy的__init__、__setattr__、__getattr__方法,以及_PorxyLookup描述器的工作过程。总结指出,g的使用基于代理模式,核心在于AppContext对象在适当时机被推送到上下文变量中。
摘要由CSDN通过智能技术生成

背景

最近有面试一家公司,感觉准备的不是很充分,感觉很多东西都答的挺菜的,自己写的文章里面的问题都没答上来更是汗流浃背。 所以大概列了一下其中的问题,进行了一番总结补充,重新制定一下复习的计划。 其中里面我觉得有个问题我觉得挺有意思的,我记得大概是问了一下Flask的g有使用过?具体实现的原理是啥?
我想了一下 ,这不就是平时用来存储一下数据的全局变量的么?有啥原理的,后面大概翻了一下Flask的源码,具体从头捋了一遍,所以就有这篇文章。

源码阅读

首先我们从平时导入的"from flask import g"入手,定位到flask框架代码中g,作为起点继续往下探索;

_cv_app: ContextVar[AppContext] = ContextVar("flask.app_ctx")
app_ctx: AppContext = LocalProxy(  # type: ignore[assignment]
    _cv_app, unbound_message=_no_app_msg
)
current_app: Flask = LocalProxy(  # type: ignore[assignment]
    _cv_app, "app", unbound_message=_no_app_msg
)
g: _AppCtxGlobals = LocalProxy(  # type: ignore[assignment]
    _cv_app, "g", unbound_message=_no_app_msg
)


这里面重要的就两块地方,_cv_app,g:

  • _cv_app这个对象实际上就是初始化一个上下文变量ContexVar,根据这个类型注解,这个上下文变量中的值是AppContext对象;
  • g实质就是_AppCtxGlobals对象,但是这里是通过LocalProxy代理对象进行访问;

LocalProxy.__init__

接下来继续分析一下LocalProxy这个代理对象是怎么代理访问_AppCtxGlobals,也就是应用上下文中的对象:(代码过长,我截取初始化中最重要的几部分)

def __init__(
        self,
        local: ContextVar[T] | Local | LocalStack[T] | t.Callable[[], T],
        name: str | None = None,
        *,
        unbound_message: str | None = None,
    ) -> None:

  • 定义传入的参数,这里local就是_cv_app上下文变量,name就是"g";
        if name is None:
            get_name = _identity
        else:
            get_name = attrgetter(name)

  • 生成一个可调用对象,用于提取对象中的属性值。后续get_name(obj)相当于直接调用obj.name属性;
        elif isinstance(local, ContextVar):

            def _get_current_object() -> T:
                try:
                    obj = local.get()
                except LookupError:
                    raise RuntimeError(unbound_message) from None

                return get_name(obj)

这部分有两

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值