本篇介绍Flask中实现数据隔离的Local类以及原理剖析
文章脉络:
- 首先我将先自行实现一个Local类
- 然后在与源码的实现方式进行比较
双下方法介绍
类的实例是可以存放数据的,我们通过“点”的方式来赋予/获取对象的属性,这是归功于类中定义的 __setattr__
方法与 __getattribute__
方法。
1 | class Foo(object): |
当然也存在错误的用法:
1 | # 例如: |
维护DATA_DICT全局字典
我们可以把数据存在DATA_DICT,对象本身可以不存储值
1 | DATA_DICT = {} |
维护storage字典
全局变量的方式是不合适的,在我们初始化一个对象后,我们给该对象封装一个名为 storage 的字典,用来存储数据。
1 | class Local(object): |
为每一个线程创建一个字典
但是上面的这个对象对于所有线程是共享数据的,我们想为每一个线程创建一个字典。所以我们修改这两个封装属性的双下划线方法,以当前线程id为key来进行存取。
1 | ''' |
- 意义:为每一个线程独立开辟空间,进行存取值!
Flask中的Local类的源码实现
1 |
|
将我们的代码与源码进行比较,发现源码做的更细致,它可以在协程级别实现数据隔离!
为什么不直接使用 threading.local
呢?
- 因为
threading.local
只能做到线程之间的数据隔离,所以需要重新定义并使用greenlet
来兼容协程。
总结
- 对象可以不直接存储数据,我们可以把数据存放在字典中,然后让这个字典做对象的属性。
- 在字典的基础上,以线程/协程id为key,值为字典,这样的设计方式可以实现不同级别的数据隔离。