博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python 21 Flask(二)上下文管理详解
阅读量:7286 次
发布时间:2019-06-30

本文共 4043 字,大约阅读时间需要 13 分钟。

上下文管理

对于上下文管理我没有找到明确的定义,但是经过源码流程的学习后,我觉得所谓的上下文管理应该就是Flask对请求和应用相关数据的一种处理方式,它不是像Django一样通过参数的传导,而是创建了全局变量直接引用,Flask为每个线程开辟一块独立的内存空间,将请求和应用相关的信息放到这个空间中,全局变量直接从这个空间中取出数据。

 

一、上下文管理流程梳理:

 

二、上下文管理图示:

 

三、源码分析

try:    from greenlet import getcurrent as get_identexcept ImportError:    try:        from thread import get_ident    except ImportError:        from _thread import get_identclass Local(object):    __slots__ = ("__storage__", "__ident_func__")    #表示只能有这两个变量    def __init__(self):        object.__setattr__(self, "__storage__", {})        object.__setattr__(self, "__ident_func__", get_ident)    #这里调用父类的方法    def __iter__(self):        return iter(self.__storage__.items())    def __call__(self, proxy):        """Create a proxy for a name."""        return LocalProxy(self, proxy)    def __release_local__(self):        self.__storage__.pop(self.__ident_func__(), None)    def __getattr__(self, name):        try:            return self.__storage__[self.__ident_func__()][name]        except KeyError:            raise AttributeError(name)    def __setattr__(self, name, value):        ident = self.__ident_func__()        storage = self.__storage__        try:            storage[ident][name] = value        except KeyError:            storage[ident] = {name: value}    def __delattr__(self, name):        try:            del self.__storage__[self.__ident_func__()][name]        except KeyError:            raise AttributeError(name)
Local对象
class LocalStack(object):    def __init__(self):        self._local = Local()    def push(self, obj):        """Pushes a new item to the stack"""        rv = getattr(self._local, "stack", None)        if rv is None:            self._local.stack = rv = []        rv.append(obj)        return rv    def pop(self):        """Removes the topmost item from the stack, will return the        old value or `None` if the stack was already empty.        """        stack = getattr(self._local, "stack", None)        if stack is None:            return None        elif len(stack) == 1:            release_local(self._local)            return stack[-1]        else:            return stack.pop()    @property    def top(self):        """The topmost item on the stack.  If the stack is empty,        `None` is returned.        """        try:            return self._local.stack[-1]        except (AttributeError, IndexError):            return None
LocalStack对象
这个对象是帮助我们去Local中取ctx或app_ctx对象的。当我们调用request.method的时候,会调用LocalProxy对象的__getattr__方法,这个方法会用LocalStack取出ctx,然后用ctx.request.method取到数据返回。其他的同理
LocalProxy对象

 

def __call__(self, environ, start_response):        """The WSGI server calls the Flask application object as the        WSGI application. This calls :meth:`wsgi_app` which can be        wrapped to applying middleware."""        return self.wsgi_app(environ, start_response)
1.请求进来执行__call__方法
def wsgi_app(self, environ, start_response):        ctx = self.request_context(environ)        error = None        try:            try:                ctx.push()                response = self.full_dispatch_request()            except Exception as e:                error = e                response = self.handle_exception(e)            except:                error = sys.exc_info()[1]                raise            return response(environ, start_response)        finally:            if self.should_ignore_error(error):                error = None            ctx.auto_pop(error)
2.调用wsgi_app方法
ReuqestContext函数中封装了request数据和sessionrequest通过传入environ原始数据实例化Request对象,处理这些原始数据,将处理好的数据返回给RequestContext的requestsession一开始是空的,会去cookie中解密并反序列化
3.其中ctx就是实例化RequestContext对象
#实际上就是RequestContext(ctx).push()#首先是实例化一个app_ctx对象,并将这个对象放入Local中        if app_ctx is None or app_ctx.app != self.app:            app_ctx = self.app.app_context()            app_ctx.push()            self._implicit_app_ctx_stack.append(app_ctx)        else:            self._implicit_app_ctx_stack.append(None)#然后将ctx放入Local中        _request_ctx_stack.push(self)
4.ctx.push

 

转载于:https://www.cnblogs.com/yinwenjie/p/10905686.html

你可能感兴趣的文章
centos7 安装iftop
查看>>
CISCO之BGP配置
查看>>
python ConfigParser 模块
查看>>
如何通过Word 2010发布文章到博客
查看>>
JVM监控和查看
查看>>
$.ajax与$.post,$.get的区别
查看>>
Java开发者易犯错误Top10
查看>>
Xcode快捷键整理(陆续添加中)
查看>>
分布式系统的事务处理
查看>>
VC 双缓存技术+滚动条
查看>>
strtol详解
查看>>
mysql部分参数注解
查看>>
Powershell常用命令总结
查看>>
HAProxy+Keepalived实现Web服务器负载均衡
查看>>
apache动静态编译
查看>>
导出到Excal表格
查看>>
nginx Rewrite 规则
查看>>
周珍:浅析百度调整的几大猜想
查看>>
微软异想天开!居然想让电脑厂商为它生产VR眼镜
查看>>
Linux Mint和LMDE将开发新版
查看>>