08.上下文

扩展

扩展阅读1

概念

上下文:相当于一个容器,保存了Flask程序运行过程中的一些信息。 在计算机中,相对于进程而言,上下文就是进程执行时的环境。具体就是各个 Flask中有两种上下文:请求上下文 、应用上下文。

Local线程隔离对象

在'Flask'中,类似于'request'的对象,其实是绑定到了一个werkzeug.local.Local对象上。这样即使是同一个对象,那么在多个线程中都是隔离的,类似的对象还有'session'以及'g'对象

Thread Local:只要绑定在Local对象上的属性,在每个线程中都是独立隔离的

from threading import Thread
from werkzeug.local import Local

local = Local()

local.request = '123'

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

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

print("主线程",local.request)

运行如下:

子线程 abc
主线程 123

应用上下文和请求上下文

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

  1. 在视图函数中,不用担心上下午呢的问题,因为视图函数要执行,那么肯定是通过访问url的方式执行的,那么这种情况下,Flask底层就已经自动的帮我们把请求上下文和应用上下文都推入到了相应的栈中。

  2. 如果想要在视图函数外面执行相关的操作,比如获取当前的app(current_app),或者是反转url,那么就必须要手动推入相关的上下文:

    • 手动推入上下文

    from flask import Flask, Response, current_app
    
    app = Flask(__name__)
    
    # 第一种方式
    app_context = app.app_context()
    app_context.push()
    
    # 第二种方式
    with app.app_context() as app_context:
        app_context.push()
        print(current_app.name)
    • 手动推入请求上下文,推入请求上下午到栈中,会首先判断有没有应用上下文,如果没有那么就会先推入应用上下文到栈中,然后推入请求上下文到栈中

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

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

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

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

线程隔离的g对象使用详解

g对象是整个flask应用运行期间都是可以使用的,并且也是跟request一样的,是线程隔离的,这个对象是专门用来存储开发者自定定义的一些数据,方便在整个flask程序中都可以使用,一般使用就是,将一些经常会用到的数据绑定到上面,以后就直接从g对象进行获取即可。

app.py

from flask import Flask, g
from test import test_g

app = Flask(__name__)

@app.route('/')
def index():
    g.name = "code"
    return "测试g对象值:{}".format(test_g())

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

test.py

from flask import g

def test_g():
    return "{}".format(g.name)

最后更新于

这有帮助吗?