1.1.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
1.2.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)
请求上下文
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.请求上下文:
如果在写测试代码,或者离线脚本的时候,我们有时候可能需要创建多个请求上下文,这时候就需要存放到一个栈中了。使用哪个请求上下文的时候,就把对应的请求上下文放到栈的顶部,用完了就要把这个请求上下文从栈中移除掉。
1.3.线程隔离的g对象
g对象是在整个Flask应用运行期间都是可以使用的,并且它也是跟request一样是线程隔离的。这个对象是专门用来存储开发者自定义的一些数据,方便在整个Flask程序中都可以使用。一般使用就是,将一些经常会用到的数据绑定到上面,以后就直接从g上面取就可以了,而不是通过传参的形式,这样更加方便。