Flask 框架理解(一)
Flask 框架理解(一)
web 服务器 , web 框架 以及 WSGI
这里说的 web 服务器特指纯粹的 python HTTP 服务器(比如 Gunicorn,而不是 Apache,Nginx这些)
一般来说, web 服务器负责建立并管理监听套接字,并且解析所有收到的 HTTP 请求。Web 框架负责 URL 分发,根据 HTTP 中请求路径生成响应。 而 WSGI(pep 333) 则是 web 服务器调用 web 框架的一个调用惯例。用来解偶 web 服务器和 web 框架。
通过 flask 的源码能比较清晰的看到这三者关系
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:
error = sys.exc_info()[1]
raise
return response(environ, start_response)
finally:
if self.should_ignore_error(error):
error = None
ctx.auto_pop(error)
def __call__(self, environ, start_response):
"""The WSGI server calls the Flask application object as the
WSGI application. This calls :meth:`wsgi_app` which can be
wrapped to applying middleware."""
return self.wsgi_app(environ, start_response)
从这里可以看出, flask 的 application 是一个 WSGI 可调用对象。如果去看 Flask Appication 的 run 方法, 就能发现最终是启动一个 Werkzeug serving.py 中的一个 基于BaseHTTPServer.HTTPServer 实现的 WSGIServer,也就是 web 服务器。证实 web 服务器通过 WSGI 接口调用 web 框架作出响应。这里也能很清楚的看到 web 框架的基础功能就是分发请求,作出响应。
理解全局变量
在 flask 中有 4 个方便好用的全局变量 current_app, request, session, g。严格意义上来说是线程级别的全局变量(具体可看 Werkzeug 的 LocalStack 源码),也就是只有当前线程能访问。正因为用的多, 更应该花点时间去理解这几个变量的含义以及生命周期。
# 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'))
对于请求-响应模式, 响应需要根据具体的请求来做出合理的响应。 这四个全局变量就是用来提供请求的具体信息,即请求上下文。从上面 wsgi_app 函数中也可以看出,有请求过来, 调用 wsig_app 时, 会构建一个当前请求的上下文实例(RequestContext),将 http 请求原始信息存到 request 属性, 并将其 push 到当前线程的全局栈 _request_ctx_stack。接着将当前 flask 实例 push 到 _app_ctx_stack, 存储到上下文实例的 app 属性中。最后解析请求中的 cookie, 构建 Session 实例存到上下文实例的 session 属性中。 这样每个请求的上下文中就携带了, http 请求的原始信息, 当前 flask 实例上下文信息, 以及 cookie 提取的 session 信息。 一个请求所需要的信息基本就全部包含了。至于 g 只是当前 flask 实例上下文对象的一个属性。在响应构造完成后, 会把当前上下文 session 信息存到 cookie,所以裸 flask 框架的 session 全部信息是存在客户端的 cookie 里面。接着弹出当前请求的上下文, 弹出当前请求的 flask 实例上下文。
def push(self):
"""Binds the request context to the current context."""
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)
if self.session is None:
session_interface = self.app.session_interface
self.session = session_interface.open_session(
self.app, self.request
)
if self.session is None:
self.session = session_interface.make_null_session(self.app)
备注:
之前有提到过, web 服务器与 web 框架是分开的,而且 WSGI 也不支持异步服务器。当 web 服务器是异步服务器时,因为 flask 存在线程级全局变量, 且是基于 Werkzeug 中基于 greenlet 的 LocalStack 上实现,所以当异步服务器不是基于 greenlet 时,会存在一定问题。
Flask 框架理解(一)的更多相关文章
- Flask框架基础--第一篇
1.flask框架和其他几种框架的优缺点对比 Django : 优点 - 大而全所有组件都是有组织内部开发高度定制化 教科书级别的框架 缺点 - 大到浪费资源,请求的时候需要的资源较高 Flask : ...
- Python Flask框架
Python有很多Web框架,可谓是百家争鸣,我这里列出几个比较叼的几个框架 Django 市场占有率最高,官方文档几近完美,但是适合比较大的项目,小项目会显得累赘. Tornado ...
- flask框架1
说flask框架之前,必须得提一下web框架,他的作用是为了利用互联网交流工作文档,我们为什么要使用框架,因为框架的稳定性和可扩展性强并且可以降低开发难度,提高开发效率.总的来说就是避免做无用功,重复 ...
- 真正搞明白Python中Django和Flask框架的区别
在谈Python中Django框架和Flask框架的区别之前,我们需要先探讨如下几个问题. 一.为什么要使用框架? 为了更好地阐述这个问题,我们把开发一个应用的过程进行类比,往往开发一个应用(web应 ...
- 一线Python运维开发带你秒懂Flask框架
相信曾经纠结过这个问题:怎样才能彻底掌握flask? Flask是一个使用 Python 编写的轻量级 Web 应用框架.其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 . ...
- Flask框架踩坑之ajax跨域请求
业务场景: 前后端分离需要对接数据接口. 接口测试是在postman做的,今天才开始和前端对接,由于这是我第一次做后端接口开发(第一次嘛,问题比较多)所以在此记录分享我的踩坑之旅,以便能更好的理解,应 ...
- 测试开发中Django和Flask框架
Python测试开发中Django和Flask框架 为了更好地阐述这个问题,我们把开发一个应用的过程进行类比,往往开发一个应用(web应用.系统应用)跟建造房子的过程一样,需要先打地基,搭好骨架,然后 ...
- Flask框架(2)--编写简单的用户注册--登录场景
为了更好的理解web前后端的工作业务逻辑:本笔记记录用flask框架编写的一个最初级的代码实现简单的用户注册,登录场景: 初次进入首页,提示--游客,欢迎参观,有登录和注册选项, 登录成功后的用户,会 ...
- 基于Flask框架搭建视频网站的学习日志(二)
基于Flask框架搭建视频网站的学习日志(二)2020/02/02 一.初始化 所有的Flask程序都必须创建一个程序实例,程序实例是Flask类的对象 from flask import Flask ...
随机推荐
- js实现深拷贝
type函数 首先我们要实现一个getType函数对元素进行类型判断,直接调用Object.prototype.toString 方法. function getType(obj){ //tostri ...
- 「HNOI2013」切糕
题目链接 戳我 \(Solution\) 对于这道题,我们首先来看看没有\(D\)这个约束的该如何做. 我们考虑构造最小割模型. 其实直接贪心就好了,选出每条路径上的最小值就好了(路径就是将每层的同一 ...
- 正确处理类的复合关系------新标准c++程序设计
假设要编写一个小区养狗管理程序,该程序需要一个“主人”类,还需要一个“狗”类.狗是有主人的,主人也有狗.假定狗只有一个主人,但一个主人可以有最多10条狗.该如何处理“主人”类和“狗”类的关系呢?下面是 ...
- windows下安装newman
1.下载安装node.js,下载地址::https://nodejs.org/en/download/,这里我下载的为v10.15.0-x64.msi,下载后直接安装即可,安装完后可输入node -v ...
- HDU6342-2018ACM暑假多校联合训练4-1011-Problem K. Expression in Memories
Problem K. Expression in Memories Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262 ...
- error while loading shared libraies :libopencv_core_so.3.4:cannot open shared object
TX2 上安装自己编译的opencv,使用时出现: error while loading shared libraies :libopencv_core_so.3.4:cannot open sha ...
- JAVA基础——编程练习(三)
熟悉String方法的使用之判断文件名是否合法 学习之余,写个小练习来巩固一下String的方法应用. 任务: 1.判断用户选择要输入的内容的类型 2.如果是java文件,输出“您输入的是java文件 ...
- Qt 学习之路 2(66):访问网络(2)
Home / Qt 学习之路 2 / Qt 学习之路 2(66):访问网络(2) Qt 学习之路 2(66):访问网络(2) 豆子 2013年10月31日 Qt 学习之路 2 27条评论 上一 ...
- 本地localhost:端口号(自己设置的Apache的端口号)打不开问题解决了!开心、哭泣
想不来自己有多蠢!历经4个月再没学,刚开始xampp的端口问题解决不了,系统竟然会自动改回去端口数据(哭晕) 后来一直显示Apache端口80占用,各种百度之后发现单纯浏览器都访问不了localhos ...
- BCH code
简单介绍 若循环码的生成多项式具有如下形式\(g(x)=LCM[m_{1}(x),m_{3}(x)..m_{2t-1}(x)]\) 其中LCM表示最小公倍式,t为纠错个数,\(m_{i}(x)\)为素 ...