上下文管理流程图、以及自己总结的源码代码
老师画的

自己整理的

同学整理的

以request.method为例,进行源码查找
from flask import Flask,request,session,g,current_app ------> request = LocalProxy(partial(_lookup_req_object, 'request')) #类后面加括号,表示是对象 ------> def __init__(self, local, name=None): ##self.__local=函数 object.__setattr__(self, '_LocalProxy__local', local) object.__setattr__(self, '__name__', name) if callable(local) and not hasattr(local, '__release_local__'): # "local" is a callable that is not an instance of Local or # LocalManager: mark it as a wrapped function. object.__setattr__(self, '__wrapped__', local) 还在这个文件下,找下面的getattr方法 def __getattr__(self, name): ##name=“method” if name == '__members__': return dir(self._get_current_object()) ##把下面的拆分成两部分,obj=self._get_current_object() ##对左边这句话的注释:去ctx中获取request ##return getattr(obj,name) 把下面这一行拆成两部分;## 这个name就是上数4行的 》》》 name=“method”这个method,是字符串,这行可改成return getattr(obj,“method”) ,也就是request.method return getattr(self._get_current_object(), name) 因为我们写的py文件中是要获取request.method,因此先要获取request,再获取method,也就是上面的去ctx中获取request,再去request中获取method, 》》》点击 return getattr(self._get_current_object(), name) ------> def _get_current_object(self): """Return the current object. This is useful if you want the real object behind the proxy at a time for performance reasons or because you want to pass the object into a different context. """ 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__) 》》同一个文件中,看看__local()是个什么鬼,请看下面代码》》 def __init__(self, local, name=None): ##self.__local = 函数,其实是最开始的那个函数 object.__setattr__(self, '_LocalProxy__local', local) object.__setattr__(self, '__name__', name) if callable(local) and not hasattr(local, '__release_local__'): # "local" is a callable that is not an instance of Local or # LocalManager: mark it as a wrapped function. object.__setattr__(self, '__wrapped__', local) 》》》接着上面说的函数,还是在同一文件下,往下走 def _get_current_object(self): """Return the current object. This is useful if you want the real object behind the proxy at a time for performance reasons or because you want to pass the object into a different context. """ 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__) 》》》看到上面之后,直接在pycharm上点击左边的一个globals.py文件,这个是我们刚看过的源码文件,找到下面这行 ------> request = LocalProxy(partial(_lookup_req_object, 'request')) ##这个就是我们上面说的函数 ------>点击上面的红色字体,进入下面 def _lookup_req_object(name):##name=request ##top=ctx(request,session) top = _request_ctx_stack.top ##_request_ctx_stack = LocalStack()就是这个对象,点击源码就能看到 if top is None: raise RuntimeError(_request_ctx_err_msg) ##获取ctx中的request对象》》(top) return getattr(top, name) 》》》》》》》》 再次回到这里__getattr__ def __getattr__(self, name): ##name=“method” if name == '__members__': return dir(self._get_current_object()) ##obj=self._get_current_object() ##去ctx中获取request 》》》》request (老师举例的就是到守夜这了) >>>>>>然后去method里面request.method就行 ##return getattr(obj,name) 等价于return getattr(obj,“method”) ,也就是request.method return getattr(self._get_current_object(), name) 》》》》》 最后回到我们写的py文件,到下面这里 request.method ##这一句相当于执行守夜.method,(本质上是这样,路程有点曲折) 》》在request.method代码下面,我们还可用下面的args方法 request.args # LocalProxy.__getattr__(key='args') # ctx中request, 再去request中获取args ,这行,其实跟上面request.method操作是一样的,点击源码进去,跟request.method都是一样的,流程也是一样的,只是换了名字,换成了args, —————————————————————————————————————————————— 下面开始看session,还是在request.method下面加一行 session['k1'] = 123 开始查看session的源码,点击我们写的代码,最上面导入的session,点进去如下 ------> session = LocalProxy(partial(_lookup_req_object, 'session')),##会到这里,发现跟上面的request是一样的,就是把request换成了session而已,也就是函数执行的默认参数不同了 ------>LocalProxy再次进去看源码 def __setitem__(self, key, value): ##obj = self.__get__current_object() ps:还继续拆分 ##obj['k1]=123 self._get_current_object()[key] = value 》》》》回到源码的globals.py文件中,点击 session = LocalProxy(partial(_lookup_req_object, 'session')) ------> 进入之后,其实就是把这些都换成了session,上面的操作是request def _lookup_req_object(name):##name=session ##top=ctx(request,session) top = _request_ctx_stack.top ##_request_ctx_stack = LocalStack()就是这个对象,点击源码就能看到 if top is None: raise RuntimeError(_request_ctx_err_msg) ##获取ctx中的session对象 return getattr(top, name) 》》》 然后再到下面看源码,还是回到刚才去过的__setitem__中 session = LocalProxy(partial(_lookup_req_object, 'session'))##这就获取到了session对象 ------> def __setitem__(self, key, value): ##obj = self.__get__current_object() 》》新加功能: 去ctx中获取session对象,(ps:session就是一个特殊的字典,因为里面有继承字典,再看下行代码注释) ##obj['k1]=123》》》新功能:在字典中赋值 self._get_current_object()[key] = value 》》》》》 上面说的赋值操作,就是我们写的代码, session['k1'] = 123 ,这就是赋值操作》》》》 session['k1'] = 123 ## LocalProxy.__setitem__(key=k1,value=123) # ctx中session, 再去session中改k1设置值 session['k1'] # #LocalProxy.__getitem__(key='k1') # ctx中session, 再去session中获取k1对应的值 这就是session里面的流程。。。 ps:问题,request和session是用的同一个ctx,也就是老师讲课举例所说的麻袋
自己写的全部py文件代码如下
from flask import Flask,request,session,g,current_app app = Flask(__name__) @app.route('/') def hello_world(): print(request) # LocalProxy.__str__ request.method # LocalProxy.__getattr__(key='method') # ctx中request, 再去request中获取method request.args # LocalProxy.__getattr__(key='args') # ctx中request, 再去request中获取args session['k1'] = 123 # LocalProxy.__setitem__(key=k1,value=123) # ctx中session, 再去session中改k1设置值 session['k1'] # LocalProxy.__getitem__(key='k1') # ctx中session, 再去session中获取k1对应的值 return 'wupeiqi' if __name__ == '__main__': app.__call__ app.wsgi_app app.run() """ 用户请求一旦到来: 1. app.__call__ """
这三个阶段,是我们自己定义的。

浙公网安备 33010602011771号