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_datetime模块和time模块

    1.datetime模块 获取当前时间: import datetime # 获取当前时间 ctime = datetime.datetime.now() print(ctime) 只显示:年-月-日 ...

  2. halcon导出类---HDevWindowStack详解

    在HDevelop中编写好的程序在导出时,Halcon会帮我们转换成我们需要的语言,比如C++.例:HDevelop中有如下语句需要导出: dev_close_window() Halcon导出成C+ ...

  3. 【模板】A*B Problem升级版(FFT快速傅里叶)

    题目描述 给出两个 $n$ 位10进制数x和y,求x*y(详见 洛谷P1919) 分析 假设已经学会了FFT/NTT. 高精度乘法只是多项式乘法的特殊情况,相当于$x=10$ 时. 例如n=3,求12 ...

  4. C# Contract诊断

    命名空间 : using System.Diagnostics.Contracts; 属性标记 : [ContractOption(category: "runtime", set ...

  5. DOM查找

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. springAop,注解annotation + redis 实现分布式锁

    当前流行的系统,就是分布式系统.所谓分布式,我个人理解,是很多的服务分布在不同的机器上,都是相同功能模块.但是容易出现一个问题,就是并发时的问题. 我们传统的锁,只能锁住一个服务器上的方法,让其在一个 ...

  7. P2634 [国家集训队]聪聪可可 点分治

    思路:点分治 提交:1次 题解: 不需要什么容斥...接着板子题说: 还是基本思路:对于一颗子树,与之前的子树做贡献. 我们把路径的权值在\(\%3\)意义下分类,即开三个桶\(c[0],c[1],c ...

  8. 检查Object是否存在某个属性

    1. in 和 hasOwnProperty in会检查对象和它的整条原型链,hasOwnProperty只会检查对象本身,不会检查原型链 let a = {name: 'rick'} let b = ...

  9. Python3.5以上Celery4.2.1启动报错:ImportError: cannot import name 'LRUCache' from 'kombu.utils.functional'

    服务器:Centos7 Python版本:Python 3.7.0 Celery版本:4.2.1 Python3.5以上,OrderDict不允许在迭代过程中进行修改,导致LRUCache.updat ...

  10. vxe-table 可编辑表格 行内编辑以及验证 element-UI集成

    <vxe-table border show-overflow ref="xTable"  ----------------------------------------- ...