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 时,会存在一定问题。
最新文章
- SSH批量部署服务
- 下载app后自动安装程序
- IOCP入门
- django的views里面的request对象详解大全
- html-制作导航菜单
- JNI调用测试
- Oracle 排序分析函数之ROW_NUMBER、RANK和DENSE_RANK
- Keepass TAN 记录的使用
- oracle数组定义与使用
- 怎么在Ubuntu Scope中获取location地址信息
- WebService支持多平台上传文件的实现
- Python3基础 setdefault() 根据键查找值,找不到键会添加
- js promise看这篇就够了
- 第一章 jQuery基础
- pytorch识别CIFAR10:训练ResNet-34(数据增强,准确率提升到92.6%)
- HTML5-之workers(多线程执行)
- MyBatis源码解析(十二)——binding绑定模块之MapperRegisty
- springboot No Identifier specified for entity的解决办法
- quora 的东西就是不一样
- centos6.8上yum安装zabbix3.2
热门文章
- SQL server T-sql语句查询执行顺序
- 以太坊系列之十四: solidity特殊函数
- Deferred Shading,延迟渲染(提高渲染效率,减少多余光照计算)【转】
- nginx理解与配置
- javascript正则表达式——元字符
- 洛谷P4502 [ZJOI2018]保镖(计算几何+三维凸包)
- Linux--CentOS7使用firewalld打开关闭防火墙与端口
- JDBC_事务概念_ACID特点_隔离级别_提交commit_回滚rollback
- express + vue 项目搭建
- HTML5 indexedDb 数据库