博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
flask接收请求并推入栈
阅读量:6510 次
发布时间:2019-06-24

本文共 2158 字,大约阅读时间需要 7 分钟。

前面两篇讲明了flask怎么支持多线程以及怎么开启多线程的,这篇来讲讲当后端接收到请求后是怎么一步步封装的

Flask类中的wsgi_app()

当应用启动后WSGI Server会通过Flask.__call__()接收http请求,Flask.__call__()中返回的是wsgi_app()方法,

def wsgi_app(self, environ, start_response):    ctx = self.request_context(environ)    ctx.push()    error = None    try:        try:            response = self.full_dispatch_request()        except Exception as e:            error = e            response = self.handle_exception(e)        except:            error = sys.exc_info()[1]            raise        return response(environ, start_response)    finally:        if self.should_ignore_error(error):            error = None        ctx.auto_pop(error)

wsgi_app()主要做了两件事情:

第一件事是通过Flask的另一个方法request_context()返回得到了一个封装好的RequsetContext对象,
ctx = self.request_context(environ),然后调用RequestContext中的push(),

class RequestContext(object):

def push(self):    app_ctx = _app_ctx_stack.top    if app_ctx is None or app_ctx.app != self.app:        app_ctx = self.app.app_context()        app_ctx.push()        self._implicit_app_ctx_stack.append(app_ctx)    else:        self._implicit_app_ctx_stack.append(None)    if hasattr(sys, 'exc_clear'):        sys.exc_clear()    _request_ctx_stack.push(self)    self.session = self.app.open_session(self.request)    if self.session is None:        self.session = self.app.make_null_session()

在最后调用了_request_ctx_stack.push(self),将请求对象推入请求上下文栈中

第二件事是在RequestContext的push()中调用app_ctx = self.app.app_context(),app_ctx.push(),将app推入应用上下文栈,
深究下去时可以发现,在RequestContext中有个app属性,它在Flask中的request_context(),也就是在wasi_app()中调用self.request_context(environ)时被赋值,

def request_context(self, environ):    return RequestContext(self, environ)

可以看到每次都传入了self,也就是Flask对象,它在RequestContext中赋值给了self.app,所以在RequestContext push()中每次推入应用上下文的app都是同一个

有两点需要注意:
1.在web runtime情况下,请求上下文和应用上下文,同时存在,同时消亡
2.创建完应用后不会立即生成应用上下文
RequestContext中放了request和session
AppContext中放了g
current_app就是AppContext对象
Local()中的__storage__这个字典格式是{thread_id:{'stack':[<RequestContext>,...]}}
所以LocalStack中的top方法返回的结果有两个:一个是RequestContext对象,一个是AppContext对象
最后抛两个问题,下次写
1.明明一个线程只能处理一个请求,那么栈里的元素永远是在栈顶,那为什么需要用栈这个结构?用普通变量不行吗.
2._request_ctx_stack和_app_ctx_stack都是线程隔离的,那么为什么要分开?

转载地址:http://izdfo.baihongyu.com/

你可能感兴趣的文章
Java集合框架2
查看>>
lock锁
查看>>
5. 星际争霸之php设计模式--抽象工厂模式
查看>>
win7下80端口被(Pid=4)占用的解决方法
查看>>
查杀linux线程指令
查看>>
关于C++ const 的全面总结
查看>>
使用嵌入式关系型SQLite数据库存储数据
查看>>
android ListView之BaseAdapter的使用方式
查看>>
css知多少(2)——学习css的思路
查看>>
Binder机制1---Binder原理介绍
查看>>
互信息概念与定理
查看>>
数据挖掘十大经典算法(9) 朴素贝叶斯分类器 Naive Bayes
查看>>
关于重写
查看>>
Linux rpm 命令参数使用详解[介绍和应用]
查看>>
**CI中的order_by在get_where之前
查看>>
[Swift] 使用Playground
查看>>
对LR analysis的平均事务响应时间和summary中时间值不同的解释
查看>>
操作系统笔记系列 一 Linux
查看>>
HDFS介绍
查看>>
Visual Studio 2013 密钥
查看>>