目录
军训结束,我又回来了!!!!!!!!!!!!!!
TreadLocal对象
需求:实现并发效果
Loacl对象
在Flask中,类似于request
对象,其实是绑定到了一个werkzeug.local.Local
对象上。
这样,即使是同一个对象,那么在多个线程中都是隔离的。类似的对象还有session
对象。
from werkzeug.local import Local
ThreadLocal变量
python提供的threadLocal变量,是一个全局变量。但是每一个线程都能保存自己的私有数据,私有数据,其他线程不可见。
在thread中的local:
from threading import Thread,local local = local() local.request='这个是请求数据1' class Mythread(Thread): def run(self): local.request='xiaolin' print(f'打印子线程的内容:{local.request}') my_thread = Mythread() my_thread.start() my_thread.join() print(f'主线程的内容:{local.request}')
在werkzeug中的local:
from threading import Thread from werkzeug.local import Local local = Local() local.request='这个是请求数据1' class Mythread(Thread): def run(self): local.request='xiaolin' print(f'打印子线程的内容:{local.request}') my_thread = Mythread() my_thread.start() my_thread.join() print(f'主线程的内容:{local.request}')
没有什么区别其实,运行效果是一样的,但是在flask中用的还是werkzeug 模块。
只要满足绑定到"local"或"Local"对象上的属性,在每个线程中都是隔离的,那么他就叫做
ThreadLocal
对象,也叫'ThreadLocal'变量。
Flask_app上下文
app上下文 = 应用上下文
理解:
程序里有很多外部变量(简单函数没有,例:add),有外部变量后,该程序就不能独立运行。要让他可以运行,则需要给所有的外部变量都设置一个值,这些值所在的集合就是上下文。(刚开始我也转不过来)
举例
运行的Flask项目,每一个路由映射的内容片段,都不可以单独拿出来使用。
当获取到了APP_Context以后,就可以直接通过程序映射的地址访问逻辑,并且可以重复使用。
应用上下文
应用上下文是存放到一个LocalStack
的栈中。和应用app相关的操作就必须要用到应用上下文。
注意
在视图函数中,不用担心应用上下文的问题。因为视图函数要执行,那么肯定是通过访问url的方式执行的,
那么这种情况下,Flask底层就已经自动的帮我们把应用上下文都推入到了相应的栈中。
注意
如果想要在视图函数外面执行相关的操作,
比如: 获取当前的app名称,那么就必须要手动推入应用上下文
例:
获取通过current_app获取当前app的名字
from flask import Flask,current_app app = Flask(__name__) #方法1 # app_ctx = app.app_context() # app_ctx.push() # print(current_app.name) #方法2 with app.app_context(): print(current_app.name) #print(current_app.name) 在没有将app推进stack里面前,不能使用。 @app.route('/') def index(): return f'hello,这是一个[{current_app.name}]引用' if __name__ == '__main__': app.run(debug=True)
用with语句可以直接帮我们把app推进stack里边。
Flask_request上下文
跟应用上下文一样,请求上下文也是存放在LocalStack 的栈中。和请求相关的操作就必须用到请求上下文。
在视图函数中,请求问题应该不需要我们去解决了,因为视图函数要执行,就肯定要通过访问url的方式来执行,这样的话Flask底层会自动帮我们把应用上下文和请求上下文都推入相应的栈中了。
但是如果要在视图函数外边进行相关的操作,就必须手动推入请求上下文。
底层代码执行说明:
1. 推入请求上下文到栈中,会首先判断有没有应用上下文
2. 如果没有那么就会先推入应用上下文到栈中
3. 然后再推入请求上下文到栈中
from flask import Flask,url_for app = Flask(__name__) @app.route('/') def index(): url = url_for('test_url') return f'hello =={url}' @app.route('/test/') def test_url(): return '这是一个测试请求上下文' # RuntimeError: Attempted to generate a URL without the application context being pushed. # This has to be executed when application context is available. # with app.app_context(): # url = url_for('test_url') # print(url) # RuntimeError: Application was not able to create a URL adapter for request independent URL generation. # You might be able to fix this by setting the SERVER_NAME config variable. with app.test_request_context(): url = url_for('test_url') print(url) if __name__ == '__main__': app.run(debug=True)
关于上下文为什么要放入栈中?
1. 应用上下文:Flask底层是基于werkzeug,werkzeug是可以包含多个app的,所以这时候用一个栈来保存。
如果你在使用app1,那么app1应该是要在栈的顶部,如果用完了app1,那么app1应该从栈中删除。方便其他代码使用下面的app。
2. 如果在写测试代码,或者离线脚本的时候,我们有时候可能需要创建多个请求上下文,这时候就需要存放到一个栈中了。
使用哪个请求上下文的时候,就把对应的请求上下文放到栈的顶部,用完了就要把这个请求上下文从栈中移除掉。