资讯专栏INFORMATION COLUMN

flask接收请求并推入栈

崔晓明 / 3182人阅读

摘要:前面两篇讲明了怎么支持多线程以及怎么开启多线程的这篇来讲讲当后端接收到请求后是怎么一步步封装的类中的当应用启动后会通过接收请求中返回的是方法主要做了两件事情第一件事是通过的另一个方法返回得到了一个封装好的对象然后调用中的在最后调用了将请求对

前面两篇讲明了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":[,...]}}
所以LocalStack中的top方法返回的结果有两个:一个是RequestContext对象,一个是AppContext对象
最后抛两个问题,下次写
1.明明一个线程只能处理一个请求,那么栈里的元素永远是在栈顶,那为什么需要用栈这个结构?用普通变量不行吗.
2._request_ctx_stack和_app_ctx_stack都是线程隔离的,那么为什么要分开?

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/44731.html

相关文章

  • 应用服务器与WSGI协议以及flask后端框架总结(后端接收请求返回响应的整个流程)

    摘要:上次遗留了两个问题先说一下自己的看法问题明明一个线程只能处理一个请求那么栈里的元素永远是在栈顶那为什么需要用栈这个结构用普通变量不行吗和都是线程隔离的那么为什么要分开我认为在的情况下是可以不需要栈这个结构的即使是单线程下也不需要原本我以为在 上次遗留了两个问题,先说一下自己的看法问题:1.明明一个线程只能处理一个请求,那么栈里的元素永远是在栈顶,那为什么需要用栈这个结构?用普通变量不行...

    tolerious 评论0 收藏0
  • Flask中的请求上下文和应用上下文

    摘要:并且栈顶的元素都是的请求上下文和应用上下文之后,我们再在这个环境中嵌套的应用上下文。这时查看两个栈的内容,发现两个栈中只有的请求的请求上下文对象和应用上下文对象。而等一直指向栈顶的请求上下文对象,分别引用请求上下文的和。 在Flask中处理请求时,应用会生成一个请求上下文对象。整个请求的处理过程,都会在这个上下文对象中进行。这保证了请求的处理过程不被干扰。处理请求的具体代码如下: de...

    sourcenode 评论0 收藏0
  • Flask内置命令行工具—CLI

    摘要:如果设置为,命令将激活模式,执行会启用交互式调试器和代码自动重载。也可以通过变量单独控制,表示启用,表示禁用通过设置环境变量略通过设置环境变量略自定义命令命令基于库实现。 应用发现 flask命令在Flask库安装后可使用,使用前需要正确配置FLASK_APP环境变量以告知用户程序所在位置。不同平台设置方式有所不同。 Unix Bash (Linux, Mac, etc.): $ ex...

    nicercode 评论0 收藏0
  • 一个Flask应用运行过程剖析

    摘要:本文就主要针对一个应用的运行过程进行简要分析,后续文章还会对框架的一些具体问题进行分析。所有的请求处理过程,都会在这个上下文对象中进行。和一些全局变量注意当进入这个上下文对象时,会触发。 相信很多初学Flask的同学(包括我自己),在阅读官方文档或者Flask的学习资料时,对于它的认识是从以下的一段代码开始的: from flask import Flask app = Flask(...

    shmily 评论0 收藏0
  • 浏览器渲染机制

    摘要:浏览器渲染进程浏览器内核进程,内部是多线程的默认每个页面一个进程,互不影响。事件触发线程归属于浏览器而不是引擎,用来控制事件循环可以理解成引擎自己都忙不过来,需要浏览器另开线程协助。 线程和进程 进程和线程的概念可以这样理解: 进程是一个工厂,工厂有它的独立资源--工厂之间相互独立--线程是工厂中的工人,多个工人协作完成任务--工厂内有一个或多个工人--工人之间共享空间 工厂有多个工人...

    appetizerio 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<