当前位置: 首页 > 编程日记 > 正文

flask 核心 之 应用上下文 及 请求上下文

Werkzeugs 是 Flask 的底层WSGI库。

什么是WSGI?

iOqdKS.jpg

一段简单的app:

def dispath_request(self, request):return Response('Hello World!')def wsgi_app(self, environ, start_response):request = Request(environ)response = self.dispath_request(request)return response(environ, start_response)

environ: 包含全部的HTTP请求信息的字典,由WSGI Server解包 HTTP 请求生成。
start_response:一个WSGI Server 提供的函数,调用可以返回相应的状态吗和HTTP报文头,函数在返回前必须调用一次。

Flask的上下文对象

Flask有两种Context(上下文),分别是

  • RequestContext 请求上下文;

    • Request 请求的对象,封装了Http请求(environ)的内容,生命周期请求处理完就结束了;
    • Session 根据请求中的cookie,重新载入该访问者相关的会话信息;
  • AppContext 应用上下文;

    • g 处理请求时用作临时存储的对象。每次请求都会重设这个变量, 生命周期请求处理完就结束了;
    • current_app 当前激活程序的程序实例,只要当前程序还在运行就不会失效。

flask 处理请求和响应的流程:

iOXDVe.png

在 'flask/globals.py' 代码中:

# context locals
_request_ctx_stack = LocalStack()   
# LocalStack 是由werkzeug提供的栈结构类提供了push、pop等方法
# 并且Local对象是werkzeug开发的类似 thinking.local(用于隔离不同线程间的全局变量) 对象,实现了在同一个协程中数据的隔离和全局性,具体怎么实现看源代码,暂时没看明白
_app_ctx_stack = LocalStack()
current_app = LocalProxy(_find_app)
# partial(_lookup_req_object, 'request') 总是返回 LocalStack 栈顶对象的 request 属性
# LocalProxy 用于代理Local对象和LocalStack对象,至于为什么使用代理。。
request = LocalProxy(partial(_lookup_req_object, 'request'))
session = LocalProxy(partial(_lookup_req_object, 'session'))
g = LocalProxy(partial(_lookup_app_object, 'g'))

flask local https://www.jianshu.com/p/3f38b777a621
为什么要使用 LocalProxy 而不直接使用 Local 和 LocalStack

# AppContext 应用上下文
#
# 在flask/app.py下:
#
def app_context(self):       # self 就是app对象return AppContext(self)#
# 在 `flask/ctx.py` 代码中
#
class AppContext(object):def __init__(self, app):self.app = appself.url_adapter = app.create_url_adapter(None)self.g = app.app_ctx_globals_class()# Like request context, app contexts can be pushed multiple times# but there a basic "refcount" is enough to track them.self._refcnt = 0def push(self):           # 这个方法就是把应用上下文push到LocalStack,AppContext类有__enter__方法"""Binds the app context to the current context."""self._refcnt += 1if hasattr(sys, 'exc_clear'):sys.exc_clear()_app_ctx_stack.push(self)appcontext_pushed.send(self.app)#
# 在 flask/cli.py 中有
#
def with_appcontext(f):@click.pass_contextdef decorator(__ctx, *args, **kwargs):    # decorator 被装饰器后 _ctx 参数是 threading 的 local() 对象with __ctx.ensure_object(ScriptInfo).load_app().app_context():   # 在这里就把 应用上下文push到了LocalStackreturn __ctx.invoke(f, *args, **kwargs)return update_wrapper(decorator, f)# RequestContext 请求上下文
#
#在flask/app.py下
#
def request_context(self, environ):     #  一次请求的环境变量return RequestContext(self, environ)#
# 在flask/ctx.py下:
#
class RequestContext(object):def __init__(self, app, environ, request=None):self.app = appif request is None:request = app.request_class(environ)self.request = requestself.url_adapter = app.create_url_adapter(self.request)self.flashes = Noneself.session = None......def push(self):..._request_ctx_stack.push(self)  #
#在flask/app.py下
#
def wsgi_app(self, environ, start_response):              # 这里类似上面的那小段简单 Werkzeugs appctx = self.request_context(environ)error = Nonetry:try:ctx.push()response = self.full_dispatch_request()except Exception as e:error = eresponse = self.handle_exception(e)except:error = sys.exc_info()[1]raisereturn response(environ, start_response)finally:if self.should_ignore_error(error):error = Nonectx.auto_pop(error)

到此从 AppContext 到 RequestContext 梳理完

app.py

源码中有这么几个装饰器:

  • before_request(self, f) # 注册一个在请求到达前要执行的函数
  • before_first_request(self, f) # 注册在整个应用实例第一个请求到达前要执行的函数
  • after_request(self, f) # 注册一个在请求处理后的函数
  • teardown_request(self, f) # 注册在请求上下文栈弹出后要执行的函数
  • teardown_appcontext(self, f) # 注册在应用上下文结束时要执行的函数
  • context_processor(self, f) # 向模板上下文中注入变量和方法,这个f必须返回一个字典, 在渲染的模板中使用
  • url_defaults(self, f) # 为应用程序中的所有视图函数 注册URL值预处理器函数。 这些函数将在:before_request函数之前调用。
  • url_value_preprocessor(self, f) # 注册一个 ‘在请求的url匹配后视图函数执行前,把环境中的某些变量换个位置存储的’ 函数
# url_defaults(self, f) 和 url_value_preprocessor(self, f) 的使用
from flask import Blueprint, render_template
profile = Blueprint('profile', __name__, url_prefix='/<user_url_slug>')
@profile.url_defaults
def add_user_url_slug(endpoint, values):values.setdefault('user_url_slug', g.user_url_slug)
@profile.url_value_preprocessor
def pull_user_url_slug(endpoint, values):g.user_url_slug = values.pop('user_url_slug')query = User.query.filter_by(url_slug=g.user_url_slug)g.profile_owner = query.first_or_404()
@profile.route('/')
def timeline():return render_template('profile/timeline.html')
@profile.route('/photos')
def photos():return render_template('profile/photos.html')
@profile.route('/about')
def about():return render_template('profile/about.html')

方法:

  • dispatch_request(self): 匹配路由,返回视图函数或者错误处理函数的返回值,并且检测是否为option请求,如果是则构造默认的 ‘options response’ 响应。构造过程首先是 Request uri 所支持的方法集(get、post、等),然后更新 Responseallow 属性(set类型),最后返回Response对象,若不是option请求则执行视图函数;
  • make_response(self, rv): rv是视图函数的返回值,在python3中,rv可以使一个元组(body、status、headers)、Response类对象、 或者一个返回Response类对象的回调函数。这个函数的功能就是把视图函数返回的 status headers 绑定到 Response;
  • create_url_adapter(self, request):url_map 适配器。对werkzeug的Map的bindbind_to_environ两个方法进行了封装。bind: 绑定一个主机地址,并返回MapAdapter对象 ; bind_to_environ( 将MAP绑定到WSGI环境中,并返回MapAdapter对象(参数script_name在进行重定向时会用到);
  • try_trigger_before_first_request_functions(self):在该实例第一个请求到达时把当前线程加锁,然后依次执行被 before_first_request(self, f)装饰过得函数,然后释放锁并把_got_first_request置为True,再次就直接return;
  • preprocess_request(self) :该函数就是执行被url_value_preprocessorbefore_request装饰过的函数;
  • full_dispatch_request(self): 先执行try_trigger_before_first_request_functions,然后执行preprocess_request,若before_request中的函数有返回值则为其构造Response,然后跳过排在此函数后边的函数包括视图函数,若before_request的函数都返回的None或没有函数就执行 dispatch_request(self)
  • inject_url_defaults(self, error, endpoint, values): 执行被'url_defaults' 装饰的函数
  • process_response(self, response): 同preprocess_request(self)

通过查看源码了解到的几个工具:

click 包 把python代码打包成命令行工具
mimetypes 包 查看文件类型
itsdangerous 签名 序列化字符串

参考资料:
Flask的核心机制!关于请求处理流程和上下文
Werkzeug(Flask)之Local、LocalStack和LocalProxy

相关文章:

vs2008中常见错误解决方法汇总

1、error C2859 vc90.idb is not the idb file that was used when this precompiled header was created。 解决方法&#xff1a;选中工程-->点击右键属性-->Configuration Properties-->C/C-->Output Files-->Program Database File Name中的$(IntDir)/vc90.p…

加速AI应用落地,英特尔AI 2.0的进阶之道

人工智能模型的复杂度不断增加&#xff0c;对内存的需求也越来越大。深度学习的进一步发展需要解决内存限制问题&#xff0c;而当前的解决方案无法利用所有可用计算&#xff0c;业内人士逐渐意识到需要专用芯片来支持深度学习训练和推理。英特尔则在人工智能方面提供优越的硬件…

MySQL基础之 恢复数据和数据库迁移

1、mysql命令或者source命令恢复数据 这两个命令在进行恢复数据的时候要检查是否创建数据库。如果数据库不存在&#xff0c;则恢复失败。 数据库迁移 1、相同版本的mysql数据库之间的迁移。 mysqldump -h host1 -uroot -ppwd --all-databases | mysql -h host2 -uroot -ppw…

.Net 文件流 System.IO之Stream

转自 &#xff1a;http://www.cnblogs.com/yukaizhao/archive/2011/07/28/stream.html Stream在msdn的定义&#xff1a;提供字节序列的一般性视图&#xff08;provides a generic view of a sequence of bytes&#xff09;。这个解释太抽象了&#xff0c;不容易理解&#xff1b…

Hinton等人最新研究:大幅提升模型准确率,标签平滑技术到底怎么用?

作者 | Rafael Mller , Simon Kornblith, Geoffrey Hinton译者 | Rachel责编 | Jane出品 | AI科技大本营&#xff08;ID: rgznai100&#xff09;【导读】损失函数对神经网络的训练有显著影响&#xff0c;也有很多学者人一直在探讨并寻找可以和损失函数一样使模型效果更好的函数…

WaitForSingleObject和WaitForMultipleObjects用法

转自&#xff1a;http://www.360doc.com/content/10/0512/09/1072296_27178529.shtml 等待函数可使线程自愿进入等待状态&#xff0c;直到一个特定的内核对象变为已通知状态为止。这些等待函数中最常用的是WaitForSingleObject: DWORD WaitForSingleObject(HANDLE hObject, DW…

【面试必问】支撑百万并发的IO多路复用技术你了解吗?

多路复用其实并不是什么新技术&#xff0c;它的作用是在一个通讯连接的基础上可以同时进行多个请求响应处理。对于网络通讯来其实不存在这一说法&#xff0c;因为网络层面只负责数据传输&#xff1b;由于上层应用协议的制订问题&#xff0c;导致了很多传统服务并不能支持多路复…

DllMain already defined in dllmain.obj错误

错误 uafxcw.lib(dllmodul.obj) : error LNK2005: DllMain already defined in dllmain.obj 修改: 去掉宏定义 _USRDLL 转载于:https://blog.51cto.com/co63oc/1122378

典型的数字水印软件

转自&#xff1a;http://blog.csdn.net/pastora/archive/2005/04/15/348413.aspx ---- 目前&#xff0c;数字水印软件既有商品化产品&#xff0c;也有供研究用的免费软件。 商品化软件 ----提供商品化数字水印软件的公司主要有以下一些&#xff1a; ----1&#xff0e;Digimar…

AI、5G、小程序、AIoT纷纷迎来高峰,下一步开发者们要怎么办?

2018 年&#xff0c;上千名开发者与上百名技术专家齐聚一堂&#xff0c;在 CSDN 2018 AI开发者大会上以“AI技术与应用”为核心&#xff0c;深度聚焦人工智能的技术创新与行业应用&#xff0c;真正做到了“只讲技术&#xff0c;拒绝空谈”。今年&#xff0c;在产业智能化的浪潮…

linux第四课

一、配置软件仓库1.yum简介基于rpm软件包的安装部署机制自动解决软件包的依赖关系需要先配置软件仓库2.配置本地的软件仓库a.放入centos7.iso镜像文件到光驱中&#xff0c;确保电源开启b.命令操作# umount /dev/cdrom# ls /mnt# mount /dev/cdrom /mnt# ls /mnt# mkdir -p /rep…

图像处理和图像识别中常用的CxImage函数

1、Load&#xff1a;reads from disk the image in a specific format&#xff1b; 2、Save&#xff1a;saves to disk the image in a specific format&#xff1b; 3、Filter&#xff1a;2D linear filter(图像锐化&#xff0c;可提高图像清晰度)&#xff1b; 4、Copy&…

大战三回合:XGBoost、LightGBM和Catboost一决高低 | 程序员硬核算法评测

作者 | LAVANYA译者 | 陆离责编 | Jane出品 | AI科技大本营&#xff08;ID: rgznai100&#xff09;【导读】XGBoost、LightGBM 和 Catboost 是三个基于 GBDT&#xff08;Gradient Boosting Decision Tree&#xff09;代表性的算法实现&#xff0c;今天&#xff0c;我们将在三轮…

云计算之Docker介绍

1. 百科简介 Docker 是一个开源的应用容器引擎&#xff0c;基于 Go 语言 并遵从Apache2.0协议开源。 Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中&#xff0c;然后发布到任何流行的 Linux 机器上&#xff0c;也可以实现虚拟化。 容器是完全使用沙…

还在纠结垃圾分类问题?带你用Python感受ImageNet冠军模型SENet的强大

作者 | beyondma转载自CSDN博客本月1日起&#xff0c;上海正式开始了“史上最严“垃圾分类的规定&#xff0c;扔错垃圾最高可罚200元。全国其它46个城市也要陆续步入垃圾分类新时代。各种被垃圾分类逼疯的段子在社交媒体上层出不穷。其实从人工智能的角度看垃圾分类就是图像处理…

软件开发流程包含哪些内容

2019独角兽企业重金招聘Python工程师标准>>> 能否开发出一个好的软件&#xff0c;关键是看软件开发前期所做的工作&#xff0c;重点是这个软件有没有一个好的 软件开发流程&#xff0c;因为一个好的软件开发流程关系到到这个软件的成败和最后能达到一个什么的效果&a…

在对话框中应用CScrollView显示图像

1、用vs2008创建一个基于对话框的工程DialogView&#xff1b; 2、添加一个新类CMyDocument&#xff0c;基类为CDocument&#xff1b; 3、添加一个新类CMyView&#xff0c;基类为CScrollView&#xff1b; 4、修改CMyDocument的头文件&#xff1a; #pragma once // CMyDocument …

如何用纯 CSS 创作一个同心圆弧旋转 loader 特效

效果预览 在线演示 按下右侧的“点击预览”按钮在当前页面预览&#xff0c;点击链接全屏预览。 https://codepen.io/zhang-ou/pen/OZmXQX 可交互视频教程 此视频是可以交互的&#xff0c;你可以随时暂停视频&#xff0c;编辑视频中的代码。 请用 chrome, safari, edge 打开观看…

Java长见到的面试题,看你能答出几题,就知道自己有多菜了

作者&#xff1a;Java3y前言只有光头才能变强Redis目前还在看&#xff0c;今天来分享一下我在秋招看过(遇到)的一些面试题(相对比较常见的)0、final关键字简要说一下final关键字&#xff0c;final可以用来修饰什么&#xff1f;这题我是在真实的面试中遇到的&#xff0c;当时答得…

数据结构实验之链表一:顺序建立链表

题目描述 输入N个整数&#xff0c;按照输入的顺序建立单链表存储&#xff0c;并遍历所建立的单链表&#xff0c;输出这些数据。输入 第一行输入整数的个数N&#xff1b;第二行依次输入每个整数。输出 输出这组整数。示例输入 8 12 56 4 6 55 15 33 62 示例输出 12 56 4 6 55 15…

深度学习在人脸检测中的应用 | CSDN 博文精选

作者 | 梁志成、刘鹏、陈方杰责编 | 唐小引转载自CSDN&#xff08;ID:csdnnews&#xff09;在目标检测领域&#xff0c;可以划分为人脸检测与通用目标检测&#xff0c;往往人脸这方面会有专门的算法&#xff08;包括人脸检测、人脸识别、人脸其他属性的识别等&#xff09;&…

vs2008中,在OCX控件中应用doc/view基本步骤

1、利用向导创建一个MFC ActiveX Control控件CMyOCX&#xff1b; 2、在工程中加入ActivDoc头文件和执行文件&#xff1b; class CActiveXDocTemplate : public CSingleDocTemplate { enum { IDR_NOTUSED 0x7FFF }; CWnd* m_pParentWnd; CFrameWnd* m_pFrameWnd; C…

常见存储过程分页PK赛——简单测试分析常见存储过程分页速度

数据的分页是我们再熟悉不过的功能了&#xff0c;各种各样的分页方式层出不穷。今天我把一些常见的存储过程分页列出来&#xff0c;再简单地测一下性能&#xff0c;算是对知识的总结&#xff0c;也是对您好想法的抛钻引玉。废话不多说&#xff0c;开始吧~~ 1.首先建立一张测试表…

YOLOv3模型剪枝,瘦身80%,提速100%,精度基本不变

作者 | CV君转载自我爱计算机视觉&#xff08;ID: aicvml&#xff09;如果要在实际应用中部署目标检测&#xff0c;你会想到哪项算法&#xff1f;在52CV目标检测交流群里&#xff0c;被提及最多的&#xff0c;恐怕就是YOLOv3了。虽然新出的一些算法号称“完胜”“吊打”某某某算…

Ubuntu开发用新机安装流程

1.SSH安装 Ubuntu缺省已安装客户端&#xff0c;此处安装服务端 sudo apt-get install openssh-server 确认sshserver是否启动 netstat -tlp | grep ssh 或 ps -e | grep ssh 未启动&#xff0c;选择启动 sudo /etc/init.d/ssh start 2.问题解决&#xff1a;ACPI Error:Method p…

人工智能六十年技术简史

出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;作者&#xff1a;李理&#xff0c;环信人工智能研发中心vp&#xff0c;十多年自然语言处理和人工智能研发经验。主持研发过多款智能硬件的问答和对话系统&#xff0c;负责环信中文语义分析开放平台和环信智能机器人的设…

【Android游戏开发二十五】在Android上的使用《贝赛尔曲线》!

首先对于《赛贝尔曲线》不是很了解的童鞋&#xff0c;请自觉白度百科、google等等... 为了方便偷懒的童鞋&#xff0c;这里给个《贝赛尔曲线》百科地址&#xff0c;以及一段话简述《贝赛尔曲线》&#xff1a; 《贝赛尔曲线》白度百科快速地址&#xff1a;http://baike.baidu.co…

Spring Boot 工程集成全局唯一ID生成器 Vesta

2019独角兽企业重金招聘Python工程师标准>>> 本文内容脑图如下&#xff1a; 文章共 760字&#xff0c;阅读大约需要 2分钟 &#xff01; 概 述 在前一篇文章 《Spring Boot工程集成全局唯一ID生成器 UidGenerator》 中给大家推荐了一款由百度开发的基于 Snowflake算…

vs2008中,创建基于对话框的mfc动态库步骤

1、利用MFC Dll向导初始生成一个mfc dll(默认设置)&#xff1b; 2、添加一个对话框资源&#xff1b; 3、向工程中添加一个.h、.cpp文件&#xff0c;作为外部的接口&#xff1b; 4、.h头文件的格式仿照于基于控制台的dll的头文件格式&#xff1b; 5、.h头文件中包括资源文件头文…

poj3468 A Simple Problem with Integers

http://acm.hust.edu.cn:8080/judge/problem/viewProblem.action?id14607 题意&#xff1a;题目给你n个数,m个操作&#xff0c;接下来一行给你这n个数&#xff0c;接下的几行给出m个操作&#xff0c;Q a b 表示查询区间[a,b]里的数和和。U a b c 表示把区间[a,b]里的数都加上c…