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. python字典的增删改查操作

    一.字典  (键值对) 1.字典的基本格式:{key1:1,key2:2} 2.字典里的键必须是不可变的(如:数字,字符串,元组,bool值);值是可变的,可用数字,字符串,列表,字典等. 3.字典里 ...

  2. Codeforces Round #584 C. Paint the Digits

    链接: https://codeforces.com/contest/1209/problem/C 题意: You are given a sequence of n digits d1d2-dn. ...

  3. 帝国CMS 7.2-插件包整合

    版权所有 2009-2019 荆门泽优软件有限公司 保留所有权利 官方网站:http://www.ncmem.com/index.aspx 产品首页:http://www.ncmem.com/weba ...

  4. codeforces 1272F dp+记录路径

    题意 给出两个括号序列 \(S\) 和 \(T\),让你构造一个最短的合法括号序列使 \(S\) 和 \(T\) 是它的子序列. 分析 设 \(dp[i][j][k]\) 为这个最短的合法括号序列的前 ...

  5. Windows 用户和内核模式

    上图: APP -> user mode OS-> kernel mode Drivers -> user or kernel mode 正所谓 一阴一阳之谓道,继之者善也,成之者性 ...

  6. Win内核原理与实现学习笔记2-现代操作系统的基本结构

    1.操作系统本属于软件的范畴,但它需要紧密的跟硬件打交道,它为上层应用软件或应用系统提供了一层抽象,专门负责硬件资源的管理和分配.(应用程序不需要跟硬件打交道,它们利用操作系统提供的功能来实现各种任务 ...

  7. 注解之 @RestController 和 @RequestMapping

    Controller 是 Spring 中最基本的组件,主要处理用户交互,一般每个业务逻辑都会有一个 Controller,供用户请求接口进行数据访问:@RequestMapping 注解用于绑定UR ...

  8. 微信小程序之简单记账本开发记录(二)

    1.打开开发者工具 2.从微信公众平台上获取到appid,或者使用测试号. 项目的大致目录如下: 一个小程序主体部分由三个文件组成,必须放在项目的根目录中 以app为开头的文件名用来布置作用于整个项目 ...

  9. 5 款最酷的 Linux 终端模拟器

    转载:https://cloud.tencent.com/developer/article/1040344 首先我要推荐的第一个终端是 Xiki. Xiki 是 Craig Muth 的智慧结晶,他 ...

  10. php mvc 模式的开发注意事项

    1.控制器中: 如果不涉及到数据库的就在控制器中. empty($res['code']) ? $this->error($res['msg']) : $this->success($re ...