一、一些python的知识

1、偏函数

def add(x, y, z):
print(x + y + z) # 原本的写法:x,y,z可以传任意数字
add(1,2,3) # 如果我要实现一个功能,这三个数中,其中一个数必须是3
# 我们就可以使用偏函数来帮着我们传参
from functools import partial # partial:给add这个函数固定传一个数字 3
new_add = partial(add, 3) # 因此新的函数只需要传2个参数
new_add(1,1)
new_add(1,2) # 偏函数:就是帮我们给一个函数固定一个参数
# new_add(x1, x2) --> add(3, x1, x2)

2、类的两个双下方法

1. __getattr__:对象获取属性值的时候触发

2. __setattr__:对象设置属性值的时候触发

3.示例
class A(object):
def __init__(self):
# self.name = {}
# 初始化的时候,给这个对象设置一个属性名为name,值为空的字典
object.__setattr__(self, "name", {}) def __getattr__(self, item):
print("getattr: ", item) def __setattr__(self, key, value):
print("setattr: ", self.name)
print("setattr: ", key, value)
self.name[key] = value
print("setattr: ", self.name) # 实例化,调用__init__
a = A() # 获取对象某个属性的值,会调用__getattr__
# 如果A这个类没有__getattr__,就会去执行父类的__getattr__
# 但是严谨的__getattr__是:如果你没有这个属性,就会给你报错
# 我们可以在A类重写__getattr__,可以让它不报错
a.xxx # getattr: xxx # 给对象的某个属性设置值,会调用__setattr__
# 执行的逻辑跟__getattr__一样,A类没有就去调用父类的
a.xxx = '小明'
# 首先打印name字典的默认值:是个空字典 setattr: {}
# setattr的key是左边的变量,value是右边的值:setattr: xxx 小明
# 打印self.name这个字典:setattr: {'xxx': '小明'}

二、Flask上下文管理

Flask的上下文管理我们可以理解为一个生命周期
也就是请求进来到请求出去一共做了哪些事情
首先我们知道项目启动执行了app.run()方法,调用了werkzeug的run_simple()方法
run_simple(host, port, self, **options) 这时候的self就是我们的app
run_simple会执行self(),也就是app(), 那么app = Flask() 所以会走Flask的__call__方法

那么__call__做了什么呢

environ是我们请求来的原始数据~当成参数传递给了request_context方法


进入这个RequestContext对象


这是初始化这个类做的一些事情
在这里重新封装了request, 以及给session 赋值了 None
也就是说:
ctx = RequestContext(app, environ)
ctx.request 是重新封装的request
ctx.session = None

继续


执行了_request_ctx_stack.push(ctx)
也就是说_request_ctx_stack它把我们的ctx对象push到了一个地方
我们的ctx这个对象里面有request以及session等

这个初始化方法就是刚才python类的双下方法__setattr__
就是给Local类初始化了两个属性    __storage__ = {}            __ident_func__ = get_ident

我们继续看LocalStark中push方法做了什么


现在回去看wsgi_app里的ctx.push(),到这里,它就走完了,接下来就要走视图
那到这里我们可以通过什么样的方法在我们视图中拿到这个request对象呢
request在ctx对象里能通过ctx.request得到,那我们怎么得到ctx呢
ctx被LocalStack对象放入到Local中了

from flask import Flask
from flask import globals app = Flask(__name__) @app.route("/")
def index():
ctx = globals._request_ctx_stack.top
print(ctx.request.method)
return "index" if __name__ == '__main__':
app.run()

获取ctx

三、Flask上下文管理(续)

这个request:
  from flask.globals import _request_ctx_stack
  ctx = _request_ctx_stack.top
  request = ctx.request

和这个request:
  from flask import request

两个request有什么区别?

其实我们导入的request跟我们上面拿到的request是一样的。

下面看看怎么直接拿request

reqeust是LocalProxy这个类的实例化对象,参数是一个偏函数,
那当我们调用request.method 等方法的时候走的是LocalProxy这个类的__getattr__方法

这里的_get_current_object()相当于我们偏函数的执行

因此,直接导入的request也是通过LocalStack方法去Local中取ctx对象
然后通过getattr 找到ctx.request,
也就是说这个LocalProxy就是一个帮助我们取值的代理,让我们的取值变的更加简单
这个代理通过偏函数来绑定参数,
ctx中封装了request,以及session,只不过到这里我们的session依然是空的。

四、session的实现原理

_request_ctx_stack.push(self)走完后,会继续走这个

也就是说,请求进来把ctx放入Local中后,从前端解密了cookie,然后把解密数据好的数据给了self.session
继续走

那么session的实现机制:
  1. 请求进来获取cookie的值
  2. 解密cookie转换成字典(没有cookie就是空字典)赋值给ctx.session
  3. 当请求走的时候把session的数据加密
  4. 设置cookie

五、应用上下文管理

应用上下文和请求上下文的原理和源码是一样的

也就是说,我们请求上下文和应用上下文,分别建立了两个Local对象
两个Local对象数据结构都是一样的,那么请求上下文和应用上下文为什么要分开存放呢
因为我们写离线脚本的时候需要用到!

小结:
也就是说可以导入请求上下文的request, session和应用上下文的g, current_app
from flask import Flask, request, session, g, current_app

六、全局对象g

我们说应用上下文里封装了g对象,那么这个g对象是什么呢
1. Flask中g的生命周期?
  我们讲这么多上下文管理,我们知道请求进来会为每个请求在Local中建立一个独立空间
  也就是在应用上下文的Local对象中建立了一个g对象,当请求走的时候就会删除
  所以g的生命周期是一次请求的进来到离开。

2. g和session有什么区别?
  session有cookie,下次请求进来的时候能带数据过来

3. g和全局对象有什么区别?
  全局变量,是在项目启动创建的,直到项目停止才会销毁
  无论多少请求进来都可以访问全局变量
  而我们的g对象一般情况用于before_request中设置值,只为这一次请求建立全局变量

4. Demo

from flask import Flask, request, session, g, current_app
from flask.globals import _request_ctx_stack app = Flask(__name__) @app.before_request
def auth():
g.xxx = "小明" @app.route("/")
def index():
ctx = _request_ctx_stack.top
print(ctx.request)
print(ctx.request.method)
print(current_app)
# request.xxx的执行过程
# 1. request --> LocalProxy(偏函数)
# 2. request.xxx --> LocalProxy __getattr__
# 3. __getattr__ --> getattr(偏函数的执行,xxx )
# 4. 偏函数--> _request_ctx_stack.top.request print(g.xxx)
return "INDEX" if __name__ == '__main__':
app.run()

七、Flask上下文管理图解

Flask上下文管理的更多相关文章

  1. Flask上下文管理、session原理和全局g对象

    一.一些python的知识 1.偏函数 def add(x, y, z): print(x + y + z) # 原本的写法:x,y,z可以传任意数字 add(1,2,3) # 如果我要实现一个功能, ...

  2. Flask上下文管理机制

    前引 在了解flask上下文管理机制之前,先来一波必知必会的知识点. 面向对象双下方法 首先,先来聊一聊面向对象中的一些特殊的双下划线方法,比如__call__.__getattr__系列.__get ...

  3. Flask 上下文管理

    为什么用threading.local? 我们都知道线程是由进程创建出来的,CPU实际执行的也是线程,那么线程其实是没有自己独有的内存空间的,所有的线程共享进程的资源和空间,共享就会有冲突,对于多线程 ...

  4. Flask上下文管理及源码刨析

    基本流程概述 - 与django相比是两种不同的实现方式. - django/tornado是通过传参数形式实现 - 而flask是通过上下文管理, 两种都可以实现,只不实现的方式不一样罢了. - 上 ...

  5. flask 上下文管理 &源码剖析

    基本流程概述 - 与django相比是两种不同的实现方式. - django/tornado是通过传参数形式实现 - 而flask是通过上下文管理, 两种都可以实现,只不实现的方式不一样罢了. - 上 ...

  6. Flask 上下文管理-- (session,request,current_app的传递)--类似本地线程实现,以及多app应用

    Flask session,request,current_app的传递 请求上下文的作用 -- 封装请求相关得数据(request,session) 请求上下文 request session re ...

  7. Flask上下文管理机制流程(源码剖析)

    Flask请求上下文管理 1 偏函数 partial 使用该方式可以生成一个新函数 from functools import partial def mod( n, m ): return n % ...

  8. Flask - 上下文管理(核心)

    参考 http://flask.pocoo.org/docs/1.0/advanced_foreword/#thread-locals-in-flask https://zhuanlan.zhihu. ...

  9. python - Flask 上下文管理 流程

    上下文管理:    - 请求上下文 (ctx=RequestContext())  : request/session    - App上下文  (app_ctx=AppContext())  : a ...

随机推荐

  1. 一款基于jQuery带事件记录的日历插件

    之前我们也已经分享过不少jQuery日历插件,有些应用了CSS3的特性,外观就特别漂亮.今天要分享的这款jQuery日历插件不仅有着绚丽的外观,而且带有日期事件记录功能,点击日期即可展开事件记录窗口, ...

  2. windows下安装配置apacheserver

    注:一開始公布的时候 图片是复制粘贴的.所以公布完图片所有消失了...如今是补发图片. . .2016/04/25 1.进入apache官网  http://httpd.apache.org/ 这里我 ...

  3. 转载:vim的复制,删除,粘贴,块操作以及快速替换功能

    掌握如下命令有什么好办法,我可以告诉你唯手熟尔!!多看多练对于VIM而言,复制,删除,粘贴的操作应该是非常多的.这次也做一个总结,关于处理VIM下的复制,删除,粘贴等操作.学会使用帮助文件,命令的帮助 ...

  4. [misc]printf/fprintf/sprintf/snprintf函数

    转自:http://blog.csdn.net/To_Be_IT_1/article/details/32179549 需要包含的头文件 #include <stdio.h> int pr ...

  5. sama5d3 环境检测 gpio--yk测试

    说明: gpio的MAP关系 yk0--pioA7  yk1--pioA5   yk2--pioA9   yk3--pioA3   yk4--pioA1  yk5--pioA8    (端子从左--& ...

  6. 【BZOJ】1697: [Usaco2007 Feb]Cow Sorting牛排序(置换群)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1697 置换群T_T_T_T_T_T_T 很久以前在黑书和白书都看过,,,但是看不懂... 然后找了本 ...

  7. xsocket:空闲超时问题。

    XSocket是什么? java的nio的封装. 详情: 1. http://xsocket.sourceforge.net/core/apidocs/2_1/index.html 2. http:/ ...

  8. LodRunner实现大负载测试的四部曲(配置系统参数、配置LR、修改脚本、设置组策略)

    见 http://www.51testing.com/?uid-97659-action-viewspace-itemid-210924 LoadRunner以下简称(LR)是目前业界最流行的压力测试 ...

  9. 编程之美 set 1 不要被阶乘吓倒

    总结 1. 使用加法解决指数问题时, 可用背包问题的变形 2. 题目用到的公式和求解 1~N 中 1 出现的次数的公式类似 题目 1. 给定一个整数 N, 那么 N 的阶乘 N! 末尾有多少个 0 呢 ...

  10. Java知识点梳理——集合

    1.定义:Java集合类存放于java.util包,是存放对象的容器,长度可变,只能存放对象,可以存放不同的数据类型: 2.常用集合接口: a.Collection接口:最基本的集合接口,存储不唯一, ...