博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
flask应用上下文和g
阅读量:5038 次
发布时间:2019-06-12

本文共 2933 字,大约阅读时间需要 9 分钟。

应用上下文

前面的请求上下文是把请求相关的封装成ctx对象放到Local对象中,应用上下文是把整个应用app自己放到Local对象中。

1112571-20180813145332813-1233484657.png

1112571-20180813145352738-2137415512.png

1112571-20180813145442568-179952076.png

1112571-20180813145535374-698832966.png

1112571-20180813145727297-1950175917.png

1112571-20180813150502429-1344596647.png

1112571-20180813150525782-1981975129.png

和应用上下文有关的全局变量
1112571-20180813150603032-1243491153.png

def _find_app():    top = _app_ctx_stack.top    if top is None:        raise RuntimeError(_app_ctx_err_msg)    return top.app
def _lookup_app_object(name):    # top 是 
, name 是 'g' top = _app_ctx_stack.top print(top, name) if top is None: raise RuntimeError(_app_ctx_err_msg) return getattr(top, name)

多app应用

flask的web开发中根据url的不同分发到不同app去处理,一个请求最终只会落到一个app的视图函数去处理

from flask import Flaskfrom werkzeug.serving import run_simplefrom werkzeug.wsgi import DispatcherMiddlewareapp1 = Flask('xx')app2 = Flask('oo')@app2.route('/index')def index():    return 'index'@app1.route('/login')def login():    return 'login'# http://127.0.0.1:5000/login 对应app1, # http://127.0.0.1:5000/backend/index 对应app2application = DispatcherMiddleware(app1, {    'backend',app2})if __name__ == '__main__':    application.__call__    run_simple('localhost', 5000, application)

其中DispatcherMiddleware.__call__源码如下:

def __call__(self, environ, start_response):        script = environ.get('PATH_INFO', '')        path_info = ''        while '/' in script:            if script in self.mounts:                app = self.mounts[script]                break            script, last_item = script.rsplit('/', 1)            path_info = '/%s%s' % (last_item, path_info)        else:            app = self.mounts.get(script, self.app)        original_script_name = environ.get('SCRIPT_NAME', '')        environ['SCRIPT_NAME'] = original_script_name + script        environ['PATH_INFO'] = path_info        return app(environ, start_response)

其实就是解析url,根据url的不同调用不同的app去处理。其中app()就会调用app.__call__, 这样就走到单app的流程中了

两个问题

为什么flask要用列表去存储上下文对象?

通过之前的了解,我们知道在单线程中,请求是一个个进行处理,也就是一个请求结束才会处理另一个请求。请求来了往列表放上下文对象,请求走了pop掉对象。下次请求来了还是循环上面的操作。即使是多线程情况下,stack的列表永远都只有一个值,既然如此,为什么还需要用列表来存值呢,不能不用列表而是直接把对象裸露地放在外面吗?确实,flask在web开发中,不会存在app嵌套app的情况,所以永远遇不到stack对应的列表中存放多个值的情况,但是如果写一个离线脚本,这个脚本用于测试flask的一些功能,就会存在app套app的情况

from flask import Flask, _app_ctx_stack, current_appapp1 = Flask('xx')app2 = Flask('oo')with app1.app_context():    print(_app_ctx_stack.top)    print(current_app)    with app2.app_context():        print(_app_ctx_stack.top)        print(current_app)    print(_app_ctx_stack.top)    print(current_app)

with 语法会在进入代码块的时候执行__enter__ ,出代码块的时候执行__exit__, 看看app1.app_context()对象的__enter__和__exit__做了些什么

1112571-20180813152840746-861368106.png

g和session的区别

通过源码流程可以知道,g的生命周期是一次请求,下一次请求拿不到上一次请求g赋的值,因上一次请求结束的时候已经被清除了。而session不同,session是把数据要么放到浏览器,要么放到数据库,虽然session对象在请求结束会被清除,但是它事先找好藏身的地方了,下次请求来的时候再去那个藏身的地方把东西拿回来。g和全局变量也不同,全局变量在flask程序启动的时候只加载一次,而g却是不断创造和销毁。

使用:因为before_request和after_request这些钩子函数和视图函数同属于一次http请求周期,通过源码就能看到那段核心代码在处理视图函数的前后分别处理了钩子函数,所以要想使用g,可以在钩子函数中使用g。在一次请求的阶段中,有后面的阶段需要用到前面阶段的值,就可以使用g。例如,如果flask没有提供session的导入,那么我们就可以在before_request中拿到session,然后g.session = session,这样在视图函数中就可以使用g.session了,类似于django内置中间件把session赋值给request对象。

转载于:https://www.cnblogs.com/longyunfeigu/p/9468569.html

你可能感兴趣的文章
【linux】重置fedora root密码
查看>>
数组的扩展
查看>>
关于空间背景颜色的操作
查看>>
HDU 6237 - A Simple Stone Game ( 分解质因数 )
查看>>
用swing做一个简单的正则验证工具
查看>>
百度坐标(BD-09)、国测局坐标(火星坐标,GCJ-02)和WGS-84坐标互转
查看>>
pig自定义UDF
查看>>
输入名字显示其生日,没有则让输入生日,做记录
查看>>
爬虫综合大作业
查看>>
HTML canvas原生js实现鼠标画图
查看>>
《程序设计入门——C语言》翁恺老师 第一周编程练习记录
查看>>
IE8兼容性视图问题
查看>>
Kubernetes 运维学习笔记
查看>>
Centos6.9下RabbitMQ集群部署记录
查看>>
Python之基本的日期与时间转换 datetime、 dateutil模块
查看>>
android studio
查看>>
色彩大全,色彩配色大全
查看>>
mpeg文件格式分析 分类: 生活百科 201...
查看>>
并查集 经典 畅通工程
查看>>
Spark MLlib 之 Naive Bayes
查看>>