RequestContetxt / AppContext对象

1.flask程序启动时

当flask程序启动时,通过源码可知,首先会创建两个LocalStack对象,二者内部会分别创建Local对象(上篇文章已经介绍LocalStack)

from flask import globals
# 进入globals可以看到如下源码:
...
# context locals
# 创建
_request_ctx_stack = LocalStack()
_app_ctx_stack = LocalStack() current_app = LocalProxy(_find_app)
request = LocalProxy(partial(_lookup_req_object, "request"))
session = LocalProxy(partial(_lookup_req_object, "session"))
g = LocalProxy(partial(_lookup_app_object, "g"))

2.用户请求到来时

第一步:实例化RequestContext对象,封装数据,得到ctx对象

当用户请求到来时,执行Flask中的__call__方法,它的作用是将请求相关的数据交由wsgi进行初步封装

# Flask源码
class Flask(_PackageBoundObject):
def __call__(self, environ, start_response):
return self.wsgi_app(environ, start_response)

wsgi_app方法

# Flask源码
class Flask(_PackageBoundObject):
# wsgi_app封装请求信息
def wsgi_app(self, environ, start_response):
# 执行request_context方法,将请求相关的所有数据封装成一个 ctx 对象
ctx = self.request_context(environ)

request_context方法

class Flask(_PackageBoundObject):
def request_context(self, environ):
# 实例化RequestContext对象
return RequestContext(self, environ)

RequestContext对象创建,封装request相关信息,主要是request和session;

class RequestContext(object):
def __init__(self, app, environ, request=None, session=None):
self.app = app
if request is None:
request = app.request_class(environ)
self.request = request
self.url_adapter = None
try:
self.url_adapter = app.create_url_adapter(self.request)
except HTTPException as e:
self.request.routing_exception = e
self.flashes = None
self.session = session

第二步:将ctx对象通过LocalStack,push到Local中进行保存

# Flask源码
class Flask(_PackageBoundObject):
# wsgi_app封装请求信息
def wsgi_app(self, environ, start_response):
# 执行request_context方法,将请求相关的所有数据封装成一个 ctx 对象
ctx = self.request_context(environ)
error = None
try:
try:
ctx.push()
response = self.full_dispatch_request()
except Exception as e:
error = e
response = self.handle_exception(e)
except: # noqa: B001
error = sys.exc_info()[1]
raise
return response(environ, start_response)
finally:
if self.should_ignore_error(error):
error = None
ctx.auto_pop(error)
class RequestContext(object):
def push(self):
top = _request_ctx_stack.top
if top is not None and top.preserved:
top.pop(top._preserved_exc)
# Before we push the request context we have to ensure that there
# is an application context.
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)
# 这里的就是通过flask启动时创建的_request_ctx_stack = LocalStack()进行push操作
...

在上述代码中可以看到,执行_request_ctx_stack.push()操作之前,会先对app_ctx对象进行操作

app_ctx对象

class Flask(_PackageBoundObject):

def app_context(self):

return AppContext(self)

-  ```python
class AppContext(object):
def __init__(self, app):
self.app = app
self.url_adapter = app.create_url_adapter(None)
self.g = app.app_ctx_globals_class()
self._refcnt = 0 def push(self):
"""Binds the app context to the current context."""
self._refcnt += 1
if hasattr(sys, "exc_clear"):
sys.exc_clear()
_app_ctx_stack.push(self)
appcontext_pushed.send(self.app)
  • 从上述代码中可知,在app_ctx对象中封装的主要是app和g;后通过app_ctx.push()实际上是_app_ctx_stack.push(self)将自己push到Local中

3.执行视图函数

full_dispatch_request

class Flask(_PackageBoundObject):
def wsgi_app(self, environ, start_response):
response = self.full_dispatch_request()

弹出Local中的请求对象

视图函数执行完毕后,要将Local中的数据进行销毁工作

class Flask(_PackageBoundObject):
def wsgi_app(self, environ, start_response):
finally:
if self.should_ignore_error(error):
error = None
ctx.auto_pop(error)

wsgi源码

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

flask上下管理文相关 - RequestContetxt & AppContext对象的更多相关文章

  1. flask上下管理文相关 - 总结

    flask上下管理文相关 - 总结 flask上下文管理机制 当用户请求到来之后,flask内部会创建两个对象: ctx = ReqeustContext(),内部封装request/sesion a ...

  2. Flask上下文管理、session原理和全局g对象

    一.一些python的知识 1.偏函数 def add(x, y, z): print(x + y + z) # 原本的写法:x,y,z可以传任意数字 add(1,2,3) # 如果我要实现一个功能, ...

  3. Flask - 上下文管理(核心)

    参考 http://flask.pocoo.org/docs/1.0/advanced_foreword/#thread-locals-in-flask https://zhuanlan.zhihu. ...

  4. Flask上下文管理机制

    前引 在了解flask上下文管理机制之前,先来一波必知必会的知识点. 面向对象双下方法 首先,先来聊一聊面向对象中的一些特殊的双下划线方法,比如__call__.__getattr__系列.__get ...

  5. Flask上下文管理机制流程(源码剖析)

    Flask请求上下文管理 1 偏函数 partial 使用该方式可以生成一个新函数 from functools import partial def mod( n, m ): return n % ...

  6. flask上下文管理之threading.local

    Flask之上下文管理 知识储备之问题情境: request中的参数: 单进程单线程 单进程多线程-->reqeust 会因为多个请求,数据发生错乱.--->可以基于threading.l ...

  7. Flask上下文管理

    一.一些python的知识 1.偏函数 def add(x, y, z): print(x + y + z) # 原本的写法:x,y,z可以传任意数字 add(1,2,3) # 如果我要实现一个功能, ...

  8. 利用StringList对象来管理这些动态生成的对象

    如果程序需要动态创建大量的对象,那么我们可以利用StringList对象来管理这些动态生成的对象.1.创建StringList对象:OBJ := TStringList.Create; 2.保存动态生 ...

  9. Linux系列教程(十四)——Linux用户和用户组管理之相关配置文件

    前面我们介绍了软件包管理.首先介绍了rpm包的相关命令,但是我们发现直接安装rpm包会被其依赖性折磨的不行,然后解决办法是yum在线管理,通过yum命令安装rpm包能自动帮助我们解决依赖性.最后又介绍 ...

随机推荐

  1. AutoMapper 的简单使用

    var config = new MapperConfiguration( cfg => cfg.CreateMap<SYS_Menu, MenuTreeNode>() .ForMe ...

  2. mali --mobile platform GPU arch about vertex pipeline

    顶点这边 我看powerVR也就是说苹果也是如此 还有mali 目前看这俩平台的顶点数据都有这样一步优化 一个render pass的所有顶点shade的时候 先算pos 用这个结果拿最上一层顶点数据 ...

  3. Vue-main.js中的一些配置

    import Vue from 'vue' import App from './App.vue' import router from './router' import store from '. ...

  4. Ubuntu 搭建 Ftp 服务器

    1.在 ubuntu 中 下载 vsftpd  要是你安装了 vsftpd  输入:vsftpd -v ,会有版本提示 如果没有,则进行安装 vsftpd 输入  apt-get install vs ...

  5. 运营中CP(X)的名词含义

    一.名词含义 我们在做产品推广时,最常见的合作方式有CPA/CPS/CPC/CPM,以及不常见的CPD/CPT/CPL,以下来详细解释这7个名词. CPA:指的是按激活或者注册付费,比如一个激活,就是 ...

  6. 11、Spring Boot 2.x 集成 HBase

    1.11 Spring Boot 2.x 集成 HBase 完整源码: Spring-Boot-Demos

  7. Python 10--模块

    可以在模块中,直接使用__file__,识别出该模块文件的路径. print __file__  

  8. python执行playbook

    from collections import namedtuple from ansible.parsing.dataloader import DataLoader from ansible.va ...

  9. leetcode解题报告(11):Search Insert Position

    描述 Given a sorted array and a target value, return the index if the target is found. If not, return ...

  10. 内存管理2-@class关键字

    Review: 给对象发送消息,进行相应的计数器操作. Retain消息:使计数器+1,改方法返回对象本身 Release消息:使计数器-1(并不代表释放对象) retainCount消息:获得对象当 ...