Flask备注三(Context)

Flask支持不同的应用场景下,对应不同的local context(本地上下文环境),用来提供当前环境下的资源。lcoal context和全局变量以及局部变量最大的不同在于,作用域是代码范围的,而local context是应用场景范围的。

Flask支持的local context包含application context以及request context。这两个都是线程安全的(基于当前的线程和request), application context存储的是和当前应用程序相关的资源,request context存储的是和当前request相关的资源和信息。

proxies

理解local context之前,首先需要理解flask的proxies。如之前所述,Flask的接口提供了一些常用的全局变量:

  • flask.current_app: 当前线程所在的application,flask支持在一个python进程中运行多个app,因此可以通过current_app获取当前所在app。
  • flask.request: 当前处理的request,只有在request处理状态可用。
  • flask.g: 用来保存状态和资源信息等任何信息。
  • flask.session: 当前app的session信息。

上述全局变量都是proxy实现的即:使用这些proxy会访问proxy指向的合适的真实对象。通过这种proxy机制,不同线程使用proxy变量时,代理根据当前的应用场景指向对应线程的变量。因此确保了变量的线程安全,并对最终对象完成了封装(大多数情况下,使用proxy,不需要关心最终对象)。但是下述情况下需要获取proxy对应的最终对象:

  • proxy并不会模拟最终对象的类型信息,如果要做示例的类型判断,则需要获取最终对象。
  • flask的singals需要传递当前application的真是引用,因此要获取最终对象。获取示例如下:

    app = current_app._get_current_object()
    my_signal.send(app)

proxy指向的对象是线程安全的,并且在不同的应用场景下不同,因此一般储存在application context 和 request context中。

request context

request conetext提供了在request处理时的上线文环境,提供了和request相关的资源。request context提供的资源只能在request处理的线程中使用。在服务器获取request时创建,并在response返回或者exception处理后销毁。

在Flask中维护一个_request_ctx_stack存储所有的request context并维持request context的生命周期。在Flask的通用request处理流程中,request context的实现如下:

  1. 通过request_context函数创建request context的对象。

    test_request_contet函数提供用户代码模拟创建request context。

  2. request context的push方法,将request context存储到_request_ctx_stack中。

  3. 当前request进行处理,将需要的资源存储到request context中。
  4. 在request处理完成或者exception处理完成后,request context通过pop方法将request context从_request_ctx_stack中弹出并释放。

    reqeust context的生命周期和request的依赖于request的处理周期,在Flask中request的处理周期如下:

    1. 在request被处理之前,所有的before_request的handler执行,如果其中有response返回则后续功能不再执行,response会替换预期的view的response。
    2. 如果没有before_request的handler返回response,则开始正常的request处理并将预定的view作为response。
    3. 正常response传入afterrequest的handler,在afterrequst的handler中可以对response进行修改和替换。
    4. 最终在request处理结束时执行teardownrequest的Handler。teardownrequest handler永远会被执行,无论是否出错以及是否执行before_request handler。

程序代码以及第三方扩展都可以修改request context保存需要的资源(更好的方式是将额外的资源存在在application context中)。reqeust context默认提供的资源包含:

  • reqeust: 当前的request对象。
  • url_adapter: 当前request所使用的url adapter。
  • session: 当前的session对象。
  • flashes: flash消息的缓存。

application context

application context提供了和当前运行application相关的local context,同样是只在当前request和线程中可用,因此也是线程安全的。生命周期和request context类似,在创建requst context时如果当前线程不存在application context,则同时创建application context。

和request context类似在application context中维护了一个_app_ctx_stack存储所有的app context并维持application context的声明周期。和request conext不同,application context默认提供的资源包含:

  • app: 当前线程所在的application,可以通过flask.current_app proxy访问。
  • g : 存储用户定义以及第三方扩展需要的资源及属性。

相比于request context,更推荐在application context中存储用户定义以及第三方扩展需要的资源。在local context中存储用户自定义资源必须要明确两点:

  • 在context中,进行隐式的存储。(在aplication context中,存储到flask.g中)
  • 在context的销毁时,完成资源的销毁。

在local context的自定义的resource,一般通过get_X()函数创建,通过teardown_X()函数销毁,其中teardown_X()函数必须注册为application context或者request context的handler。示例如下:

import sqlite3
from flask import g def get_db():
db = getattr(g, '_database', None)
if db is None:
db = g._database = connect_to_database()
return db @app.teardown_appcontext
def teardown_db(exception):
db = getattr(g, '_database', None)
if db is not None:
db.close()

同样,和其他的proxy一样,可以将这个资源声明为LocalProxy。

from werkzeug.local import LocalProxy
db = LocalProxy(get_db)

这样我们可以通过db来访问get_db函数。

Flask备注三(Context)的更多相关文章

  1. Flask 备注一(单元测试,Debugger, Logger)

    Flask 备注一(单元测试,Debugger, Logger) Flask是一个使用python开发Web程序的框架.依赖于Werkzeug提供完整的WSGI支持,以及Jinja2提供templat ...

  2. Flask备注二(Configurations, Signals)

    Flask备注二(Configuration, Signals) Flask是一个使用python开发Web程序的框架.依赖于Werkzeug提供完整的WSGI支持,以及Jinja2提供templat ...

  3. Flask备注4(Structure)

    Flask备注4(Structure) package 通过Flask可以非常简单的通过一个module(一个py文件)创建一个简单的application.这种简单程序的文件结构如下: /youra ...

  4. Flask 上下文(Context)原理解析

    :first-child { margin-top: 0; } blockquote > :last-child { margin-bottom: 0; } img { border: 0; m ...

  5. flask基础三

    一.路由和视图(基础二上补充) (1)有参装饰器 路由采用的是有参装饰器实现的 @app.route("/index",methods=["GET"," ...

  6. docker 部署 flask(三)高级编写及生成镜像,安装requirements.txt

    简介: 上一篇,我写了如何使用别人的docker基础镜像,生成我们的docker镜像. 也就最基本的flask,没有别的库(包)支持.连数据库支持都没有. 也就让大家了解一下怎么生成镜像而已. 本篇介 ...

  7. Flask第三篇——安装Flask

    现在我们来安装Flask: Windows系统安装Flask 如果你的系统是Windows,那安装起来非常方便——pip install flask Mac系统安装Flask Mac安装Flask一般 ...

  8. flask系列三之Jinja2模板

    1.如何渲染模板 模板在‘templates’文件夹下(htnl页面) 从flask中导入render_template函数---渲染html模板 在视图函数中,使用render_template 函 ...

  9. flask 学习(三)

    继续flask的学习.尝试了使用程序context这一部分: 而在hello.py文档的旁边发现新出现了hello.pyc,看来运行过程中也被编译成字节码文件了,也不清楚是在哪个步骤的,留着后面研究. ...

随机推荐

  1. SQL Server提高事务复制效率优化(三)订阅初始化优化

    初始化订阅主要是由分发代理分发和应用快照代理之前生成的快照,所以优化的主体是分发代理. 1.初始化订阅 首先在本地创建一个订阅,发布服务器.分发服务器和订阅服务器都在同一台服务器上,仅为了测试生产环境 ...

  2. over partition by与group by 的区别

    (本文摘自scottpei的博客) over partition by与group by 的区别 今天看到一个老兄的问题, 大概如下: 查询出部门的最低工资的userid 号 表结构: D号      ...

  3. 解决vs2008无法切换设计视图的问题

    在 Visual Studio 2008的编辑一个web页面的时候,“源视图”(Source View), 你可以自定义设计视图(Design View)为默认视图. 方法如下: 菜单:工具+选项+h ...

  4. 《SSM框架搭建》一.构建maven web项目

    一.创建maven工程File-New-other-Maven Project 二.设置项目工作空间,取消默认勾选,手动设置 三.选择internal,输入web,选择maven.archetypes ...

  5. PHP大文件存储示例,各种文件分割和合并(二进制分割与合并)

    最近要对视频进行上传,由于涉及到的视频非常的大,因此采用的是分片上传的格式,下面是一个简单的例子: split.php <?php $i = 0; //分割的块编号 $fp = fopen(&q ...

  6. win7和Ubuntu双系统折腾记

    哎,最近老是写些没涵养的博客.哥们问我怎么不分享点cv的论文思路,或者搞点深度学习调参的经验.因为真正跑深度学习搞 计算机视觉的时候,时间悄悄过去了,只有环境出Bug了,才是我最难受的时候,每一次搞好 ...

  7. Res_Orders_01需求分析

    一.背景及好处 为了提高餐厅的运营效率,增强餐厅各部门间的配合,减少顾客到店后的点餐.等餐及结算过程消耗的时间,降低服务员点餐失误率,进一步提高餐厅管理人员对菜品.资金的管理以及更好的掌握餐厅的全局运 ...

  8. c#接口容易被忽视的问题

    今天在看"并发集合"的时候,接口IProducerConsumerCollection<T> 有一个方法是TryAdd(),表示"试图"去添加,然后 ...

  9. js浏览器对象的属性和方法

    1.window对象 /*1.计算浏览器窗口大小*/ //不算滚动条: var width = window.innerWidth; var height = window.innerHeight; ...

  10. 316. Remove Duplicate Letters

    Given a string which contains only lowercase letters, remove duplicate letters so that every letter ...