Python Flask上下文管理机制实例解析


Posted in Python onMarch 16, 2020

前言

上下文这个概念多见于文章中,是一句话中的语境,也就是语言环境。一句莫名其妙的话出现会让人不理解什么意思,如果有语言环境的说明,则会更好,这就是语境对语意的影响。

上下文是一种属性的有序序列,为驻留在环境内的对象定义环境。在对象的激活过程中创建上下文,对象被配置为要求某些自动服务,如同步、事务、实时激活、安全性等等。

如在计算机中,相对于进程而言,上下文就是进程执行时的环境。具体来说就是各个变量和数据,包括所有的寄存器变量、进程打开的文件、内存信息等。可以理解上下文是环境的一个快照,是一个用来保存状态的对象。在程序中我们所写的函数大都不是单独完整的,在使用一个函数完成自身功能的时候,很可能需要同其他的部分进行交互,需要其他外部环境变量的支持,上下文就是给外部环境的变量赋值,使函数能正确运行。

请求上下文

关于WSGI

WSGI(全称Web Server Gateway Interface),是为 Python 语言定义的Web服务器和Web应用程序之间的一种简单而通用的接口,它封装了接受HTTP请求、解析HTTP请求、发送HTTP,响应等等的这些底层的代码和操作,使开发者可以高效的编写Web应用。

Flask提供了两种上下文,一种是应用上下文(Application Context),一种是请求上下文(Request Context)。

  • RequestContext 请求上下文
  • Request 请求的对象,封装了Http请求(environ)的内容
  • Session 根据请求中的cookie,重新载入该访问者相关的会话信息。
  • AppContext 程序上下文
  • g 处理请求时用作临时存储的对象。每次请求都会重设这个变量
  • current_app 当前激活程序的程序实例

参见Flask上下文官方文档 请求上下文 和 应用上下文.

  1. application 指的就是当你调用app = Flask(__name__)创建的这个对象app;

2.request 指的是每次http请求发生时,WSGI server(比如gunicorn)调Flask.call()之后,在Flask对象内部创建的Request对象;

3.application 表示用于响应WSGI请求的应用本身,request 表示每次http请求;

4.application的生命周期大于request,一个application存活期间,可能发生多次http请求,所以,也就会有多个request

生命周期

  • current_app的生命周期最长,只要当前程序实例还在运行,都不会失效。
  • Request和g的生命周期为一次请求期间,当请求处理完成后,生命周期也就完结了
  • Session就是传统意义上的session了。只要它还未失效(用户未关闭浏览器、没有超过设定的失效时间),那么不同的请求会共用同样的session。

Flask处理流程

Python Flask上下文管理机制实例解析

local线程隔离对象

不用local对象的情况

from threading import Thread

request = '123'

class MyThread(Thread):
  def run(self):
    global request
    request = 'abc'
    print('子线程',request)  #子线程 abc

mythread = MyThread()
mythread.start()
mythread.join()

print('主线程',request)     #主线程 abc

如果用local对象,在每个线程中都是隔离的

from threading import Thread
from werkzeug.local import Local

locals = Local()
locals.request = '123'

class MyThread(Thread):
  def run(self):
    locals.request = 'abc'
    print('子线程',locals.request)  #子线程 abc

mythread = MyThread()
mythread.start()
mythread.join()

print('主线程',locals.request)     #主线程 123

app上下文和request上下文

应用上下文和请求上下文都是存放在一个‘LocalStack'的栈中,和应用app相关的操作就必须要用到应用上下文,比如通过current_app获取当前的这个app的名字。和请求相关的操作就必须用到请求上下文,比如使用url_for反转视图函数。

在视图函数中,不用担心上下文的问题,因为视图函数要执行,name肯定是通过访问url的方式执行的,name这种情况下,Flask底层就已经自动的帮我们把请求上年文和应用上下文都推入到了相应的栈中。如果想要在视图函数外面执行相关的操作,name就必须要手动推入相关的上下文手动推入请求上下文:推入请求上下文到栈中,会首先判断有没有应用上下文,如果没有那么就会先推入应用上下文到栈中,然后再推入请求上下文到栈中。

app上下文

from flask import Flask,current_app

app = Flask(__name__)

#如果在视图函数外部访问,则必须手动推入一个app上下文到app上下文栈中
#第一种方法
# app_context = app.app_context()
# app_context.push()
# print(current_app.name)

#第二种方法
with app.app_context():
  print(current_app.name)   #context_demo

@app.route('/')
def index():
  # 在视图函数内部可以直接访问current_app.name
  print(current_app.name)  #context_demo
  return 'Hello World!'

if __name__ == '__main__':
  app.run(debug=True)

request请求上下文

from flask import Flask,current_app,url_for

app = Flask(__name__)

#应用上下文
#如果在视图函数外部访问,则必须手动推入一个app上下文到app上下文栈中
with app.app_context():
  print(current_app.name)   #context_demo

@app.route('/')
def index():
  # 在视图函数内部可以直接访问current_app.name
  print(current_app.name)  #context_demo
  return 'Hello World!'

@app.route('/list/')
def my_list():
  return 'my_list'

# 请求上下文
with app.test_request_context():
  # 手动推入一个请求上下文到请求上下文栈中
  # 如果当前应用上下文栈中没有应用上下文
  # 那么会首先推入一个应用上下文到栈中
  print(url_for('my_list'))

if __name__ == '__main__':
  app.run(debug=True)

为什么上下文需要放在栈中?

1.应用上下文:

Flask底层是基于werkzeug,werkzeug是可以包含多个app的,所以这时候用一个栈来保存,如果你在使用app1,那么app1应该是要在栈的顶部,如果用完了app1那么app应该从栈中删除,方便其他代码使用下面的app。

2.应用上下文:

如果在写测试代码,或者离线脚本的时候,我们有时候可能需要创建多个请求上下文,这时候就需要存放到一个栈中了。使用哪个请求上下文的时候,就把对应的请求上下文放到栈的顶部,用完了就要把这个请求上下文从栈中移除掉。

线程隔离的g对象

g对象是在整个Flask应用运行期间都是可以使用的,并且它也是跟request一样是线程隔离的。这个对象是专门用来存储开发者自定义的一些数据,方便在整个Flask程序中都可以使用。一般使用就是,将一些经常会用到的数据绑定到上面,以后就直接从g上面取就可以了,而不是通过传参的形式,这样更加方便。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python算法学习之基数排序实例
Dec 18 Python
python在不同层级目录import模块的方法
Jan 31 Python
Python2中文处理纪要的实现方法
Mar 10 Python
Python GUI布局尺寸适配方法
Oct 11 Python
Python清空文件并替换内容的实例
Oct 22 Python
从列表或字典创建Pandas的DataFrame对象的方法
Jul 06 Python
Python 使用 docopt 解析json参数文件过程讲解
Aug 13 Python
python识别文字(基于tesseract)代码实例
Aug 24 Python
DJango的创建和使用详解(默认数据库sqlite3)
Nov 18 Python
python接入支付宝的实例操作
Jul 20 Python
详解非极大值抑制算法之Python实现
Jun 28 Python
python函数的两种嵌套方法使用
Apr 02 Python
Python threading.local代码实例及原理解析
Mar 16 #Python
python实现ssh及sftp功能(实例代码)
Mar 16 #Python
借助Paramiko通过Python实现linux远程登陆及sftp的操作
Mar 16 #Python
Django ValuesQuerySet转json方式
Mar 16 #Python
Django 再谈一谈json序列化
Mar 16 #Python
django实现将后台model对象转换成json对象并传递给前端jquery
Mar 16 #Python
Python读写操作csv和excle文件代码实例
Mar 16 #Python
You might like
异世界新番又来了,同样是从零开始,男主的年龄降到5岁
2020/04/09 日漫
PHP实现采集程序原理和简单示例代码
2007/03/18 PHP
PHP 作用域解析运算符(::)
2010/07/27 PHP
比较时间段一与时间段二是否有交集的php函数
2011/05/31 PHP
windows7下安装php的imagick和imagemagick扩展教程
2014/07/04 PHP
php中get_cfg_var()和ini_get()的用法及区别
2015/03/04 PHP
PHP使用CURL实现多线程抓取网页
2015/04/30 PHP
thinkphp5框架实现数据库读取的数据转换成json格式示例
2019/10/10 PHP
发两个小东西,ASP/PHP 学习工具。 用JavaScript写的
2007/04/12 Javascript
alixixi runcode.asp的代码不错的应用
2007/08/08 Javascript
一个js封装的不错的选项卡效果代码
2008/02/15 Javascript
jQuery dialog 异步调用ashx,webservice数据的代码
2010/08/03 Javascript
利用JQuery制作符合Web标准的QQ弹出消息
2014/01/14 Javascript
jquery使用jxl插件导出excel示例
2014/04/14 Javascript
jquery datepicker参数介绍和示例
2014/04/15 Javascript
JavaScript中的getMilliseconds()方法使用详解
2015/06/10 Javascript
jQuery Validation Engine验证控件调用外部函数验证的方法
2017/01/18 Javascript
Bootstrap栅格系统简单实现代码
2017/03/06 Javascript
Vue2.0基于vue-cli+webpack父子组件通信(实例讲解)
2017/09/14 Javascript
p5.js入门教程之键盘交互
2018/03/19 Javascript
VUE项目中加载已保存的笔记实例方法
2019/09/14 Javascript
webpack HappyPack实战详解
2019/10/08 Javascript
[01:10:49]Secret vs VGJ.S 2018国际邀请赛淘汰赛BO3 第二场 8.24
2018/08/25 DOTA
Python中的包和模块实例
2014/11/22 Python
在Python中使用模块的教程
2015/04/27 Python
python实现在pandas.DataFrame添加一行
2018/04/04 Python
Python使用matplotlib和pandas实现的画图操作【经典示例】
2018/06/13 Python
python 批量解压压缩文件的实例代码
2019/06/27 Python
python 使用多线程创建一个Buffer缓存器的实现思路
2020/07/02 Python
详解向scrapy中的spider传递参数的几种方法(2种)
2020/09/28 Python
Old Navy加拿大官网:美式休闲服饰品牌
2017/09/26 全球购物
Kingsoft金山公司C/C++笔试题
2016/05/10 面试题
测绘工程系学生的自我评价
2013/11/30 职场文书
中学生社会实践活动总结
2014/07/03 职场文书
升职自荐信怎么写
2015/03/05 职场文书
同学聚会致辞集锦
2015/07/28 职场文书