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