day93 请求上文文总结分析

请求上下文总结分析

from flask import Flask

app = Flask(__name__)

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

'''
整个flask的源码:
    def wsgi_app(self, environ, start_response):
        # ctx就是 RequestContext的一个对象 里面包含了请求相关的所有东西
        ctx = self.request_context(environ)
        error = None
        try:
            try:
                # 把ctx放到了Local对象里
                ctx.push()
                #请求扩展以及响应函数
                response = self.full_dispatch_request()
            except Exception as e:
                error = e
                response = self.handle_exception(e)
            except:  # noqa: B001
                error = sys.exc_info()[1]
                raise
            return response(environ, start_response)
        finally:
            if self.should_ignore_error(error):
                error = None
            ctx.auto_pop(error)
            
            
1 ctx = self.request_context(environ)---》ctx本质是RequestContext的对象
    1.1 RequestContext(self, environ):self是当前的app,environ是请求相关的
    1.2 RequestContext(self, environ)执行的结果是RequestContext类的对象,该对象中包含了请求相关和当前app
    1.3 所以这个ctx就是RequestContext的对象
     
2 ctx.push():当前ctx是RequestContext的对象,那就是执行RequestContext对象的push方法
    2.1 ctx.push方法中有一个_request_ctx_stack.push(self);这个self是ctx,那就是把ctx传递个_request_ctx_stack
    
    2.2 _request_ctx_stack就是LocalStack的对象
    
    2.3 _request_ctx_stack.push  
    源码如下:
        #obj就是_request_ctx_stack.push(self)传过来的self,也就是ctx
        def push(self, obj):
            rv = getattr(self._local, "stack", None)
            if rv is None:
                #_local=local -->setattr
                # storage[线程/协程id][stack] = []
                self._local.stack = rv = []
            # storage[线程/协程id][stack] = [obj,]
            rv.append(obj)
            return rv
            
        2.3.1 在2.3的代码中self._local.stack做的事情
            发现self._local是Local对象,所以self._local就执行了Local对象的__setattr__:
            代码如下:
                def __setattr__(self, name, value):
                    ident = self.__ident_func__()
                    storage = self.__storage__
                    try:
                        storage[ident][name] = value
                    except KeyError:
                        storage[ident] = {name: value}
    总结:
        就是将ctx放到Local对象以storage[ident][stack] = [ctx,]的形式存储


3 response = self.full_dispatch_request() 这里面是所有请求扩展以及真正的响应函数
源码如下:
    def full_dispatch_request(self):
        self.try_trigger_before_first_request_functions()
        try:
            request_started.send(self)
            rv = self.preprocess_request()
            #如果请求扩展中的,请求之前的所有函数,如果没有返回值,就会执行下面的
            #下面的是:请求路由中的函数
            if rv is None:
                rv = self.dispatch_request()
        except Exception as e:
            rv = self.handle_user_exception(e)
        return self.finalize_request(rv)
        
    3.1 self.try_trigger_before_first_request_functions()
    这是在请求扩展中的before_first_request
    他是如何判断项目启动后只执行一次里面的方法:
        通过self._got_first_request变量来判断的,初始值为False,一旦执行过了该函数,在函数的末尾将self._got_first_request设置成True
    源码如下:
        def try_trigger_before_first_request_functions(self):
            if self._got_first_request:
                return
            with self._before_request_lock:
                if self._got_first_request:
                    return
                #这里去循环第一次执行的函数,请求扩展的里面
                for func in self.before_first_request_funcs:
                    func()
                self._got_first_request = True
                
    3.2 rv = self.preprocess_request() 这里执行的是befor_request的函数
    源码如下:
        def preprocess_request(self):
            bp = _request_ctx_stack.top.request.blueprint
            
            funcs = self.url_value_preprocessors.get(None, ())
            if bp is not None and bp in self.url_value_preprocessors:
                funcs = chain(funcs, self.url_value_preprocessors[bp])
            for func in funcs:
                func(request.endpoint, request.view_args)
            # 请求之前要做的事情,请求之前的请求扩展
            funcs = self.before_request_funcs.get(None, ())
            if bp is not None and bp in self.before_request_funcs:
                funcs = chain(funcs, self.before_request_funcs[bp])
            for func in funcs:
                rv = func()
                if rv is not None:
                    return rv
                    
        3.2.1 funcs = self.before_request_funcs.get(None, ())这里是获取所有注册进来的befor_request
        
        3.2.2 下面的代码可以看出:如果befor_request函数有一个返回值,那么后面的函数都不执行,并且把返回值给rv = self.preprocess_request()里的rv
            for func in funcs:
                rv = func()
                if rv is not None:
                    return rv
                    
    3.3 if rv is None: #这个rv是3.2中before_request返回的,如果没有返回值,才会执行rv = self.dispatch_request(),有返回值就不会执行
                rv = self.dispatch_request()#这个是真正的响应函数
        通过这个代码:知道如果before_request有返回值,就不会执行真正的响应函数
        
    3.4 return self.finalize_request(rv):这个rv是3.2或3.3的返回值
    源码如下:
        def finalize_request(self, rv, from_error_handler=False):
            response = self.make_response(rv)
            try:
                # 这里执行的是执行完请求视图后,after_request的请求
                response = self.process_response(response)
                request_finished.send(self, response=response)
            except Exception:
                if not from_error_handler:
                    raise
                self.logger.exception(
                    "Request finalizing failed with an error while handling an error"
                )
            return response
            
        3.4.1 response = self.process_response(response):这里做after_request请求扩展的
        源码如下:
            def process_response(self, response):
                ctx = _request_ctx_stack.top
                bp = ctx.request.blueprint
                funcs = ctx._after_request_functions
                if bp is not None and bp in self.after_request_funcs:
                    funcs = chain(funcs, reversed(self.after_request_funcs[bp]))
                if None in self.after_request_funcs:
                    funcs = chain(funcs, reversed(self.after_request_funcs[None]))
                for handler in funcs:
                    response = handler(response)
                if not self.session_interface.is_null_session(ctx.session):
                    self.session_interface.save_session(self, ctx.session, response)
                return response
            在上述代码有两行代码
                if None in self.after_request_funcs:
                #funcs是所有after_request的函数列表,并用reversed做了反转
                #这里就知道在after_request里为什么先注册的后执行
                    funcs = chain(funcs, reversed(self.after_request_funcs[None]))
                for handler in funcs:
                    #在这里知道after_request的函数必须接受这response,并且要做返回
                    response = handler(response)

4 我们知道3中就可以调用request属性,那么是怎么做到的呢
    当我们在3中的任意位置,都能调用request或者其他的。比如我们调用request.methons,他是如何找到当前请求的request的呢
    
    4.1 当我们调用request.methons的时候,我们先要看看request是什么
    源码如下:
        request = LocalProxy(partial(_lookup_req_object, "request"))#也就是LocalProxy对象
        
    4.2 当我们调用request.method就会返回属性methons属性给我吗,但是我们在LocalProxy根本没有methons属性,那么我们想到,既然没有这个属性,一定会走__getattr__
    源码如下:
        def __getattr__(self, name):
            #name就是methons
            if name == "__members__":
                return dir(self._get_current_object())
            #_get_current_object中来取name也就是methods
            #_get_current_object()执行的结果是partial(_lookup_req_object, "request")()==》就是从ctx中取到request
            #下面的意思就是getattr(request,methons)
            return getattr(self._get_current_object(), name)
        上述代码的name,及时我们要找的methons,那他是从self._get_current_object()通过反射来拿的
        从下面的分析中 我们知道self._get_current_object()就是request
        
        4.2.1 self._get_current_object()的返回值是什么:
        通过下面的源码我们可以看到就是self.__local()的执行结果
        源码如下:
            def _get_current_object(self):
                if not hasattr(self.__local, "__release_local__"):
                    return self.__local()
                try:
                    return getattr(self.__local, self.__name__)
                except AttributeError:
                    raise RuntimeError("no object bound to %s" % self.__name__)
                    
            4.2.1.1 self.__local()的执行结果是什么?首先要搞清楚self.__local是什么
                我们发现self.__local是通过如下初始化得到的
                    def __init__(self, local, name=None):
                        object.__setattr__(self, "_LocalProxy__local", local)
                那我们可以知道self.__local就是4.1中LocalProxy(partial(_lookup_req_object, "request"))的参数
                也就是partial(_lookup_req_object, "request")偏函数
                
            4.2.1.2 我们现在知道self.__local是partial(_lookup_req_object, "request")
                那self.__local()就是partial(_lookup_req_object, "request")()执行
                
            4.2.1.3 partial(_lookup_req_object, "request")相当于给_lookup_req_object函数传递了一个“request”参数
                _lookup_req_object,源码如下:
                    #name就是request
                    def _lookup_req_object(name):
                        #Local中取得ctx
                        top = _request_ctx_stack.top
                        #top就是ctx
                        if top is None:
                            raise RuntimeError(_request_ctx_err_msg)
                        #ctx中去request 在吧request返回回去
                        return getattr(top, name)
                我们从4.2.1.3.1得知 top就是ctx,getattr(top, name)就是从ctx找request,并且返回
                4.2.1.2中self._local执行的结果就是request
                
                4.2.1.3.1 
                    上述代码中_request_ctx_stack.top的源码如下:
                    @property
                    def top(self):
                        try:
                            #返回了一开始存进去的ctx对象
                            return self._local.stack[-1]
                        except (AttributeError, IndexError):
                            return None
                    self._local也是Local对象 .stack就是在执行__getattr__
                    代码如下:
                        def __getattr__(self, name):
                            try:
                                return self.__storage__[self.__ident_func__()][name]
                            except KeyError:
                                raise AttributeError(name)
            这样_request_ctx_stack.top得到的结果就是ctx,4.2.1.3中的top = _request_ctx_stack.top;top就是ctx
'''

g对象

from flask import Flask,g
'''
专门用来给开发者存储信息的,他只在同一个请求内有效
'''
app=Flask(__name__)

@app.before_request
def b_r():
    g.name="egon is sb"#存
    g.name="egon is dsb"

@app.after_request
def a_r(response):
    print(g.name)
    print(g.age)
    return response


@app.route("/")
def index():
    g.age="egon"
    print(g.name)#取
    return "ok"

@app.route("/login")
def login():
    return "login"

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

flask-script

'''
pip install flask-script
bu用右键启动  改为命令行启动
命令行:python s3.py runserver 或者 python3 s3.py runserver  s3是py文件的文件名
'''
from flask import Flask
from flask_script import Manager
app=Flask(__name__)
manager=Manager(app)

@app.route("/")
def index():
    return "ojbk"

'''
命令行启动下面的函数
python s3.py etom 123
s3是py文件名  etom是函数名  123是参数 函数没有参数就不用谢
'''
@manager.command
def etom(arg):
    print("我把excl导入到myslq")
    print(arg)

'''
命令行启动:
python s3.py cmd -n egon -y haha
python s3.py cmd -y hah  -n egon
python s3.py cmd --you hah  -n egon
python s3.py cmd --you hah  --name egon
-n  --name -y --you:就相当于形参
函数里的形参名要和dest一致
'''
@manager.option("-n","--name",dest="name")
@manager.option("-y","--you",dest="you")
def cmd(name,you):
    print(name,you)

if __name__ == '__main__':
    manager.run()

猜你喜欢

转载自www.cnblogs.com/zqfzqf/p/12392252.html
93
L93