Flask 源码剖析 (四):Flask 的上下文机制 (下)

本文深入探讨Flask的上下文机制,包括为何使用werkzeug的Local类而非threading.local,将上下文分为请求上下文和应用上下文的原因,LocalStack的作用以及为何使用LocalProxy进行数据访问。通过分析,阐述了这些设计在多应用和内部重定向等场景中的必要性。
摘要由CSDN通过智能技术生成

前言

本文紧接着「Flask 源码剖析 (三):Flask 的上下文机制 (上)」,讨论如下问题。

  • 1.Python 中有 thread.local 了,werkzeug 为什么还要自己弄一个 Local 类来存储数据?

  • 2. 为什么不构建一个上下文而是要将其分为请求上下文 (request context) 和应用上下文 (application context)?

  • 3. 为什么不直接使用 Local?而要通过 LocalStack 类将其封装成栈的操作?

  • 4. 为什么不直接使用 LocalStack?而要通过 LocalProxy 类来代理操作?

回顾 Flask 上下文

在上一篇文章中,详细讨论了 Flask 上下文机制,这里简单回顾一下。

所谓 Flask 上下文,其实就是基于 list 实现的栈,这个 list 存放在 Local 类实例化的对象中,Local 类利用线程 id 作为字典的 key,线程具体的值作为字典的 values 来实现线程安全,使用的过程就是出栈入栈的过程,此外,在具体使用时,会通过 LocalProxy 类将操作都代理给 Local 类对象。

为何需要 werkzeug 库的 Local 类?

treading 标准库中已经提供了 local 对象,该对象实现的效果与 Local 类似,以线程 id 为字典的 key,将线程具体的值作为字典的 values 存储,简单使用如下。

In [1]: import threading
In [2]: local = threading.local()
In [3]: local.name = '二两'
In [4]: local.name
Out[4]: '二两'

那为何 werkzeug 库要自己再实现一个功能类似的 Local 类呢?

主要原因是为了兼容协程,当用户通过 greenlet 库来构建协程时,因为多个协程可以在同一个线程中,threading.local 无法处理这种情况,而 Local 可以通过 getcurrent () 方法来获取协程的唯一标识。

# werkzeug/local.py
# since each thread has its own greenlet we can just use those as identifiers
# for the context.  If greenlets are not available we fall back to the
# current thread ident depending on where it is.
try:
    from greenlet import getcurrent as get_ident
except ImportError:
    try:
        from thread import get_ident
    except ImportError:
        from _thread import get_ident

为什么要将上下文分为多个?

回顾一下问题。

为什么不构建一个上下文而是要将其分为请求上下文 (request context) 和应用上下文 (application context)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

懒编程-二两

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值