当前位置: 首页 > news >正文

flask接收请求并推入栈

前面两篇讲明了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都是线程隔离的,那么为什么要分开?

相关文章:

  • 从PRISM开始学WPF(八)导航Navigation?
  • 手把手教你将单机游戏改造成对战网游(附详细教程)
  • P2264 情书
  • Spring Boot的@Service和@Autowired和@ComponentScan注解
  • 两个变量交换的四种方法(Java)
  • 分布式消息队列ActiveMQ+Spring整合
  • Vue2.x学习三:事件处理生命周期钩子
  • MySQL的prompt不生效的问题
  • Django之ModelForm(二)-----ModelForm组件
  • Lua使用总结
  • Python模块-threading模块
  • xtrabackup 备份原理
  • tkinter简单打开网址 + 执行系统命令
  • flask学习笔记之flask-migrate
  • 项目实战 (规范、轮子、学习案例) - iOS
  • 【140天】尚学堂高淇Java300集视频精华笔记(86-87)
  • 【EOS】Cleos基础
  • bearychat的java client
  • Essential Studio for ASP.NET Web Forms 2017 v2,新增自定义树形网格工具栏
  • javascript从右向左截取指定位数字符的3种方法
  • Java多线程(4):使用线程池执行定时任务
  • PhantomJS 安装
  • Spring技术内幕笔记(2):Spring MVC 与 Web
  • 对象引论
  • 多线程 start 和 run 方法到底有什么区别?
  • 记录一下第一次使用npm
  • 快速体验 Sentinel 集群限流功能,只需简单几步
  • 前端性能优化--懒加载和预加载
  • 使用API自动生成工具优化前端工作流
  • 组复制官方翻译九、Group Replication Technical Details
  • ​TypeScript都不会用,也敢说会前端?
  • ​卜东波研究员:高观点下的少儿计算思维
  • ​中南建设2022年半年报“韧”字当头,经营性现金流持续为正​
  • ## 临床数据 两两比较 加显著性boxplot加显著性
  • (+3)1.3敏捷宣言与敏捷过程的特点
  • (Demo分享)利用原生JavaScript-随机数-实现做一个烟花案例
  • (附源码)spring boot车辆管理系统 毕业设计 031034
  • (附源码)计算机毕业设计SSM智能化管理的仓库管理
  • (附源码)计算机毕业设计高校学生选课系统
  • (强烈推荐)移动端音视频从零到上手(下)
  • (数位dp) 算法竞赛入门到进阶 书本题集
  • (原創) 如何刪除Windows Live Writer留在本機的文章? (Web) (Windows Live Writer)
  • (终章)[图像识别]13.OpenCV案例 自定义训练集分类器物体检测
  • (转)Oracle 9i 数据库设计指引全集(1)
  • (转载)Linux 多线程条件变量同步
  • .bat批处理(七):PC端从手机内复制文件到本地
  • .net core IResultFilter 的 OnResultExecuted和OnResultExecuting的区别
  • .net 前台table如何加一列下拉框_如何用Word编辑参考文献
  • .skip() 和 .only() 的使用
  • /dev/VolGroup00/LogVol00:unexpected inconsistency;run fsck manually
  • ?php echo ?,?php echo Hello world!;?
  • @LoadBalanced 和 @RefreshScope 同时使用,负载均衡失效分析
  • @RequestBody详解:用于获取请求体中的Json格式参数
  • [ 云计算 | AWS 实践 ] Java 如何重命名 Amazon S3 中的文件和文件夹
  • [145] 二叉树的后序遍历 js