文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Flask的上下文管理详解

2023-06-02 01:59

关注

本篇内容介绍了“Flask的上下文管理详解”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

Flask线程间上下文安全

Falsk完成线程安全的原理,是在启动之后进程里维护request栈和app栈,栈是通过线程ID来保证每个请求的线程安全。

实现主要依赖三个类Local,LocalStack和LocalProxy,下面看一下具体的实现原理

三个类构建本地数据

Local

先看Local的源码,实质并不是Flask中定义的,而是Flask依赖的werkzeug库所定义。

可以看到其定义的两个属性__storage__, __ident_func__以及三个方法__getattr__,__setattr__,__release_local__。

属性__storage__是多层级字典,第一层key是隐含的线程ID或者协程ID,第二层的key是实际使用的关键字

属性__ident_func__可以看到是get_ident函数,get_ident函数要么是通过thread库获取当前执行单元的线程ID,要么是通过greenlet库获取当前执行协程的协程ID。

另外可以看到Local这个类的三个方法,实质是通过重写Python内置函数__setattr__和__getattr__来实现线程或者协程间数据隔离

获取local某属性时如:local.age实质触发的是__getattr__方法先获取到当前线程ID——__ident_func__函数获取,然后在__storage__字典中找到线程ident对应的结果集从获取到的结果中再查找age属性

设置local某属性时如:local.age = 12 实际触发的是__setattr__方法先获取到当前线程ID——__ident_func__函数获取,然后在__storage__字典设置相应的属性字典集

另一个__release_local__方法就是将相应的线程数据删除。

画个简图比较起来更直观一些。

Flask的上下文管理详解

主线程中生成一个对象local=Local(),三个线程中进行相同的操作local.no=每个线程对应的数。为每个线程都开辟一个存储,所以谁来取或者存就找到自己对应中的位置,虽然取得key都一样,但是每次存取都是只关于自己的值。

LocalStack

LocalStack也是定义在Flask所依赖的werkzeug库,从字面意思来理解,它就是Local的堆栈操作,看一下源码如何定义。

LocalStack实质就是围绕着Local来进行操作,根据上面我们读完Local的源码可以看到,

  1. LocalStack定义了一个Local对象

  2. 给这个对象设置了一个stack属性,且这个属性是一个列表

  3. LocalStack中定义了对这个列表进行压栈,出栈等方法

  4. 给类中的Local对象提供了自定义ident_func的方法

LocalProxy

LocalProxy字面意思就是做一个Local的代理,我们先从一个request的定义来看LocalProxy的用法,然后结合源码来看LocalProxy到底是用来做什么?

类中稍微有些难理解的就是关于object.__setattr__(self, “_LocalProxy__local”, local)的作用,实际就是给self设置一个__local属性。这是Python类中关于私有变量的定义。可以看Python的官方定义python私有变量。

可以看到这个类将所有Python类所内置的方法都进行重写,重写后所有的操作都是基于类中所定义的_get_current_object方法返回的对象进行操作。

而这个方法中返回值就是初始化时所给定的local对象执行返回的结果。如果创建时指定的不是Local对象,则直接执行此方法。如果给定的是Local对象,则根据类名查找对应的对象。

现在这个比较抽象,这个代理到底是做的什么? 我们结合Flask定义全局的request对象来看。假如我们想获取请求的方法是什么,那我们使用的就是request.method。

下面是request定义的源码

  1. 根据LocalProxy的源码中重写的__getattr__方法,先执行_get_current_object方法获取到对象,然后再获取返回对象method属性。

  2. 创建LocalProxy时传递的函数是_lookup_req_object的偏函数,实际就是_lookup_req_object且name=request

  3. 再LocalProxy中__local就是一个函数,所以在执行_get_current_object就是执行_lookup_req_object且name=request返回的值,然后再取其method属性

  4. 此时再执行_lookup_req_object函数,从_request_ctx_stack获取top的request

使用Proxy可以简单快捷的使用request.method获取相应的值,其核心就是每次获取时都会执行对应的函数,而函数中每次返回的值都是线程安全。保证数据正确且优雅。 否则我们每次都去执行一个函数来获取其值,然后再取其属性。

“Flask的上下文管理详解”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯