zoukankan      html  css  js  c++  java
  • Flask 上下文管理-- (session,request,current_app的传递)--类似本地线程实现,以及多app应用

    Flask session,request,current_app的传递

    请求上下文的作用 -- 封装请求相关得数据(request,session)
    

      请求上下文
    
    	request
    	session
    
    	request local类 {线程,协程的唯一ID:{stack:[RequestContext(request,session)]}} 
    
      应用上下文
    
    	app local类 {线程,协程的唯一ID:{stack:[AppContext(app,g)]}} 
                
                   # app 保存着 应用相关的值
                   # g  每次请求周期都会创建一个用于在请求周期中传递值 的 容器
    

    1 flask的 request, session 和 current_app 都是 设置方式比较新颖 -- 通过上下文管理的方式实现的

    类似于本地线程 threading_local ,创建Local类
    
    local = {
            '线程或者协程的唯一标识':{'stack':[RequestContext(),]},  # a   每个线程一份
            '线程或者协程的唯一标识':{'stack':[RequestContext(),]},  # b
            '线程或者协程的唯一标识':{'stack':[RequestContext(),]},  # c
            '线程或者协程的唯一标识':{'stack':[RequestContext(),]},  # d
            '线程或者协程的唯一标识':{'stack':[RequestContext(),]},  # e
    
            }
    
        每次请求进来app.run调用 call 方法, 将包含了所有请求相关数据的实例对象RequestContext()添加, 通过stack(键),push到一个地方Local中,使用的时候再去取(top方法取值),在请求结束后返回的时候  pop 掉
    

    与Django的区别

    请求相关数据的传递方式 :                                                
        
        Django  
            参数一个一个传递
        
        Flask
            基于Local(类似于本地线程)和LocalStack(push, pop, top)完成
            参数不用来回传递, 直接获取reqeust
        
        多个请求一起数据也不会混淆
        
            单线程 - - 每次只能有一个请求处理
            多线程 - -  通过Local实现不同的数据划分 - -   thread - -线程的唯一标识
            协程 - -     greenlet - - 协程的唯一标识
    

    flask 的上下文管理机制描述

    (1)	与django相比是两种不同的方式实现:
    
      	django/tornado 是通过传参的方式
    
    	flask 第通过上下文管理机制
    
    	两种都可以实现,只是实现的方式不一样
    
    (2)类似 threading local 机制,
         flask创建  一个local类 {线程,协程的唯一ID:{stack:[RequestContext(request,session)]}}  保证数据隔离
    
     		请求进来 把ReqeustContext对象 push到 对应的stack中
     		使用 的时候 通过localstack的top方法,获取local中的reqeust
     		请求终止  通过localstack pop方法,删除local的request
    
    
    
       
    

    2 补充 partial 函数

    其实就是函数调用的时候,有多个参数 参数,但是其中的一个参数已经知道了,我们可以通过这个参数重新绑定一个新的函数,然后去调用这个新函数。
    
    from functools import partial
    
    def f(a,b):
        return a + b
    
    f1 = partial(f,10)
    
    print(f1(5))
    -->> 15
    

    3 唯一标识

    基于 Local类
    
    类似于本地线程theading_local  -->> 每一个线程 创建一个
    
    from greenlet import getcurrent as get_ident
    可以基于 greenlet -->> 粒度更细
    
            比如 wsgi  -- 有基于线程的,也有基于协程实现的
    
    
    本地线程:
                    
    
        import threading
    
        local_values = threading.local()
    
    
        def func(num):
            local_values.name = num
            import time
            time.sleep(1)
            print(local_values.name, threading.current_thread().name)
    
    
        for i in range(20):
            th = threading.Thread(target=func, args=(i,), name='线程%s' % i)
            th.start()
    

    4 多app应用,以及web'访问多app时的上下文

    多app应用,通过前缀做分发
    
    from werkzeug.wsgi import DispatcherMiddleware
    from werkzeug.serving import run_simple
    
    app1 = Flask('app1')
    app2 = Flask('app2')
    
    @app1.route('/index')
    def index():
    	return 's'
    
    @app2.route('/index')
    def index():
    	return 's'
    
    dm = DispatcherMiddleware(app1,{'/app2':app2})
    
    if __name__ == '__main__':
    	run_simple('localhost',5000,dm)
    
    
    同时并发的请求 app1 和 app2,请求上下文Local类中 {
        'ID app1':{stack:[ReqeustContext,]},
        'ID app2':{stack:[ReqeustContext,]},
    }
    

    5 补充 with .. 上下文管理

    class SQLHelper(object):
    
    	def __enter__(self):
    		print('开始')
    		self.open()
    		return self
    
    	def open(self):
    		pass
    
    	def fetch(self):
    		pass
    
    	def close(self):
    		pass
    
    	def __exit__(self, exc_type, exc_val, exc_tb):
    		print('结束')
    		self.close()
    
    
    with SQLHelper() as f:
    	pass
    

    6 为什么 flask的 local 保存数据要使用 列表建成的栈

    #  如果是 web 程序,栈中永远是 一条数据 (可以不使用栈)
    #  如果是 脚本测试 出现如下的上下文嵌套 ,会出现 多条数据
    
    from flask import Flask,current_app,_app_ctx_stack
    
    app1 = Flask(__name__)
    app1.config['DEBUG'] = True
    
    app2 = Flask(__name__)
    app2.config['DEBUG'] = False
    
    
    with app1.app_context():
        print(_app_ctx_stack._local.__storage__)
        print(current_app.config['DEBUG'])  # current_app  _app_ctx_stack.top [-1]
    
        with app2.app_context():
            print(_app_ctx_stack._local.__storage__)
            print(current_app.config['DEBUG'])
    
                    #  {5116: {'stack': [<flask.ctx.AppContext object at 0x00000000038C55C0>, <flask.ctx.AppContext object at 0x00000000038C5748>]}}     False
    
  • 相关阅读:
    Linux记录-批量安装zabbix(转载)
    k8s-基础环境配置(六)
    k8s记录-ntpd时间同步配置(五)
    k8s记录-flanneld+docker网络部署(四)
    Java面试通关要点汇总集
    Java并发编程系列
    码农需要知道的“潜规则”
    领域驱动设计文章
    自动化测试的一些思考
    轻量级爬虫框架
  • 原文地址:https://www.cnblogs.com/big-handsome-guy/p/8545154.html
Copyright © 2011-2022 走看看