zoukankan      html  css  js  c++  java
  • flask-本地线程-请求上下文补充

    context(上下文)是flask里面非常好的设计,使用flask需要非常理解应用上下文和请求上下文这两个概念

    本地线程

    本地线程(thread local)希望不同的线程对于内容的修改只在线程内部发挥作用,线程内部互相不影响

    from django.test import TestCase
    import threading
    
    mydata = threading.local()
    mydata.number = 42
    
    print(mydata.number)
    
    logs = []
    
    
    def f():
        mydata.number = 11
        logs.append(mydata.number)
    
    
    thread = threading.Thread(target=f)
    thread.start()
    thread.join()
    print(mydata.number)

    可以看到,在线程的内部修改了mydata.number的值,但是没有影响到开始设置的值

    本地线程的实现原理就是:在threading.current_thread().__dict__里添加一个包含对象mydata的id值的key,来保存不同的线程状态

    werkzeug的Local

    werkzeug自己实现了自己的本地线程。werkzeug.local.Local和threading.local的区别如下:
    
    werkzeug使用了自定义的__storage__来保存不同线程下的状态
    
    werkzeug提供了释放本地线程的release_local方法
    
    werkzeug使用了两种方法来通过get_ident函数获取线程的标识符*(greenlet,系统线程,默认使用系统的,如果安装了greenlet则使用她)

    werkzeug还实现了两种数据结构。

    localstack:基于werkzeug.local.Local实现的栈结构,可以将对象推入,弹出,也可以快速拿到栈顶对象
    
    localproxy:作用和名字一样,是标准的代理模式。构造次结构时接收一个可以调用的参数(一般是函数),这个函数执行后就是通过localstack实例化的栈的栈顶对象。
    
         基于localproxy对象的操作实力上都会转发到这个栈顶对象(也就是一个threadlocal上边)

    Flask.request

    from flask import Flask, request
    
    app = Flask(__name__)
    
    
    @app.route('/')
    def xxx():
        name = request.args.get("name")

    在这里,我们先引用了flask.request,但是直到用户访问xxx函数的使用才通过request.args.get获取请求的参数值,试想,引用的时候还没发生这个请求,那么请求上下文是怎么获得的呢?

    flask.request就是一个获取名为_request_ctx_stack的栈顶对象的LocalProxy实例:

    from functools import partial
    from werkzeug.local import LocalProxy
    
    def _lookup_req_object(name):
        top = _request_ctx_stack.top
        if top is None:
            raise RuntimeError("xxxxx")
        return getattr(top, name)

    上面的逻辑可以正常使用,先来看看流程:

    1:用户访问产生请求
    2:在发生请求的过程中向_reqeust_ctx_stack推入这个请求的上下文对象,他会变成栈顶,request就会成为这个请求上下文,也就包含了这次请求的相关信息和数据
    3:在视图函数中使用request就可以使用request.args.get('name')了
    设想不使用LocalStack和LocalProxy的话,要想让视图函数访问的请求对象,就只能将其作为参数,一步步的传入视图函数中。这样做的缺点是会让每个视图函数都增加一个request参数,
    而flask却巧妙的使用了上下文把某些对象设置成全局访问,每个线程看到的上下文对象却是不同的,这样就巧妙的解决了这个问题

    使用上下文

    应用上下文的典型场景是缓存一些在发生请求之前要使用到的资源,比如生成数据库链接和缓存一些对象;请求上下文发生在HTTP请求的开始,WSGI server调用Flask.__call__()之后。
    应用上下文并不是应用启动之后生成的唯一上下文

    ······有空写吧,该吃饭了。。

  • 相关阅读:
    二叉树非递归遍历
    二叉树之统计二叉树的节点个数
    C语言32个关键字(2)
    C语言32个关键字(1)
    C语言常用字符串操作函数总结
    面向对象的四大特征
    C语言之生产者与消费者模型
    菜鸟随笔(4)---read函数与fread函数的区别
    菜鸟随笔(3)---三种进程学习.孤儿进程.僵尸进程.守护进程
    进程通信——管道、消息队列、共享内存、信号量
  • 原文地址:https://www.cnblogs.com/52-qq/p/9340804.html
Copyright © 2011-2022 走看看