Flask核心机制--上下文源码剖析

 

一、前言

  了解过flask的python开发者想必都知道flask中核心机制莫过于上下文管理,当然学习flask如果不了解其中的处理流程,可能在很多问题上不能得到解决,当然我在写本篇文章之前也看到了很多博文有关于对flask上下文管理的剖析都非常到位,当然为了学习flask我也把对flask上下文理解写下来供自己参考,也希望对其他人有所帮助。

二、知识储备

threadlocal

  在多线程中,线程间的数据是共享的, 但是每个线程想要有自己的数据该怎么实现? python中的threading.local对象已经实现,其原理是利用线程的唯一标识作为key,数据作为value来保存其自己的数据,以下是demo演示了多个线程同时修改同一变量的值的结果:

复制代码
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # Author:wdimport threading import time values=threading.local()  def run(arg):     values.num=arg  #修改threading.local对象的name数据    time.sleep(1)     print(threading.current_thread().name,values.num)  #打印values.numfor i in range(3):     th = threading.Thread(target=run, args=(i,), name='run thread%s' % i)     th.start()   结果: run thread0 0 run thread1 1 run thread2 2
复制代码

结果说明:

从结果中可以看到,values.num的值是不同的,按照普通线程理解因为有sleep存在,在每个线程最后打印values.num时候值应该都是2,但是正是因为threading.local对象内部会为每个线程开辟一个内存空间,从而使得每个线程都有自己的单独数据,所以每个线程修改的是自己的数据(内部实现为字典),打印结果才不一样。

有了以上的设计思想,我们可以自己定义类似于thread.local类,为了支持协程,将其唯一标识改为协程的唯一标识,其实这已经及其接近flask中的Local类了(后续在进行说明):

复制代码
try:     from greenlet import getcurrent as get_ident  # 携程唯一标识except ImportError:     try:         from thread import get_ident     except ImportError:         from _thread import get_ident  # 线程唯一标识class Local(object):     def __init__(self):         object.__setattr__(self, 'storage', dict())  # 防止self.xxx 递归        object.__setattr__(self, '__get_ident__', get_ident)      def __setattr__(self, key, value):         ident = self.__get_ident__()  # 获取当前线程或协程的唯一标识        data = self.storage.get(ident)         if not data:  # 当前线程没有数据            data = {key: value}  # 创建数据        else:  # 当前已经有数据            data[key] = value          self.storage[ident] = data  # 最后为当前线程设置其标识对应的数据    def __getattr__(self, name):         try:             return self.storage[self.__get_ident__()].get(name)  # 返回name所对应的值        except KeyError:  
                    
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信