flask 源码剖析

上下文本质 

- 当请求过来后,将请求相关数据添加到 Local()类中
	{ 
		线程或协程唯一标识:{"stack":[request]},
		线程或协程唯一标识:{"stack":[]},
		线程或协程唯一标识:{"stack":[]}
	}
- 以后使用时 去读取
- 请求完成之后,将request从列表中移除

Flask源码

from flask import Flask,session,request

app = Flask(__name__)

@app.route("/login",methods=["GET","POST"])
def login():
    return "index"

if __name__ == '__main__':
    #app.__call__()
    app.run()

1. 执行app.__call__方法

def __call__(self, environ, start_response):
        return self.wsgi_app(environ, start_response)

2. 执行wsgi_app方法

def wsgi_app(self, environ, start_response):

    ctx = self.request_context(environ)
    ctx.push()

    response = self.full_dispatch_request()

2.1 生成RequestContext()对象 封装请求相关的数据(request,session)

ctx = self.request_context(environ)
def request_context(self, environ):
    return RequestContext(self, environ)

class RequestContext(object):
    def __init__(self, app, environ, request=None):
           self.app = app
           if request is None:
            request = app.request_class(environ)
           self.request = request

2.2 将用户请求数据封装到Local()类中

ctx.push()
def push(self):

    from .globals import _request_ctx_stack

    #将请求数据封装到Local()类
    _request_ctx_stack.push(self)

    #处理session
    self.session = self.app.open_session(self.request)
    if self.session is None:
        self.session = self.app.make_null_session()

2.2.1 导入 _request_ctx_stack对象  内部会自动生成  { 线程或协程唯一标识:{"stack":[]} } 格式 

from .globals import _request_ctx_stack
class Local(object):

    def __init__(self):
        object.__setattr__(self, '__storage__', {})
        object.__setattr__(self, '__ident_func__', get_ident)

    def __setattr__(self, name, value):
        ident = self.__ident_func__()
        storage = self.__storage__
        try:
            storage[ident][name] = value
        except KeyError:
            storage[ident] = {name: value}


class LocalStack(object):

    def __init__(self):
        self._local = Local()

    def push(self, obj):
        rv = getattr(self._local, 'stack', None)
        if rv is None:
            self._local.stack = rv = []
        rv.append(obj)
        return rv

_request_ctx_stack = LocalStack()

2.2.2 执行_request_ctx_stack对象push方法  触发Local的__setattr__执行     生成  { 线程或协程唯一标识:{"stack":[ RequestContext对象 ]} }

_request_ctx_stack.push(self)
class Local(object):

    def __setattr__(self, name, value):
        ident = self.__ident_func__()
        storage = self.__storage__
        try:
            storage[ident][name] = value
        except KeyError:
            storage[ident] = {name: value}


class LocalStack(object):

    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

_request_ctx_stack = LocalStack()

2.2.3 self.session重新赋值

RequestContext类的 self.session由none重新赋值为SecureCookieSessionInterface类open_session方法的结果(SecureCookieSession对象)
	- SecureCookieSession对象 就是一个字典

self.session = self.app.open_session(self.request)
def open_session(self, request):
    return self.session_interface.open_session(self, request)
 
# 之后这里可以自定义自己类 可以继承SecureCookieSessionInterface类
session_interface = SecureCookieSessionInterface()

class SecureCookieSessionInterface(SessionInterface):

    def open_session(self, app, request):
        s = self.get_signing_serializer(app)
        if s is None:
            return None

        # 去cookie中获取session作为key 对应的值(包含了此用户的session数据) 
        val = request.cookies.get(app.session_cookie_name)
        if not val:
            return self.session_class()
        max_age = total_seconds(app.permanent_session_lifetime)
        try:
            data = s.loads(val, max_age=max_age)
            return self.session_class(data)
        except BadSignature:
            return self.session_class()

3. 之后调用request

#此时你如果调用request 会执行如下代码
request = LocalProxy(partial(_lookup_req_object, 'request'))
    _lookup_req_object 获取RequestContext()中用户的请求数据

4. 执行视图函数

response = self.full_dispatch_request()

4.1 触发只执行一次的装饰器函数 @before_first_request 

self.try_trigger_before_first_request_functions()

4.2 # 触发Flask的信号  需要pip3 install blinker

request_started.send(self)

4.3 执行特殊装饰器  @before_request

有返回值 返回用户 
没有返回值 触发并执行视图函数
rv = self.preprocess_request()
if rv is None:
    rv = self.dispatch_request()

4.4 执行请求之后的装饰器  @after_request  且处理session

return self.finalize_request(rv)

    def finalize_request(self, rv, from_error_handler=False):

        response = self.process_response(response)

            def process_response(self, response):

                # 处理session
                if not self.session_interface.is_null_session(ctx.session):
                self.save_session(ctx.session, response)

 

 

 

 

 

  

  

 

  

  

  

 

posted @ 2018-01-09 23:05  golangav  阅读(380)  评论(0编辑  收藏  举报