关于flask中 RuntimeError: Working outside of application context 引发的问题(flask中的上下文机制)
一、问题引出:当在测试文件里直接要获得flask核心对象app时(即不启动服务器),按照下面的方式会报出error,如下图看似和平时获得app对象没有什么不同,但是这种方法是获取不到的,这就引出了flask中的上下文机制。二、flask的上下文机制1.flask中存在应用上下文(AppContext)和请求上下文(RequestContext),flask的核心对象...
一、问题引出:
当在测试文件里直接要获得flask核心对象app时(即不启动服务器),按照下面的方式会报出error,如下图
看似和平时获得app对象没有什么不同,但是这种方法是获取不到的,这就引出了flask中的上下文机制。
二、flask的上下文机制
1.flask中存在应用上下文(AppContext)和请求上下文(RequestContext),flask的核心对象被存储在AppContext应用上下文中,即AppContext是对flask核心对象app进行了封装;项目中的请求信息Request会被存储在RequestContext请求上下文中
2.通过阅读源码可以看到,这两个上下文对象都存在push()、pop()、enter()、exit()四个方法。
(1)根据上图,当一个请求进入我们的flask项目中,flask框架会实例化一个RequestContext对象,这次请求的相关信息Request被封装在RequestContext里,准备压入栈中(即push操作)。在flask中,栈是通过LocalStack这个对象实现的,实例化LocalStack这个对象并赋给_request_ctx_stack。
(2)当要把RequestContext压入栈之前,flask会检查 _app_ctx_stack这个栈中是否有值,如果该栈为空,那么flask会再实例化一个AppContext对象,封装了核心对象app,压入_app_ctx_stack这个栈中(也就是说,如果请求到达,_app_ctx_stack中没有值,那么flask会先将AppContext封装当前对象先压栈,再将RequestContext压栈)注意入栈先后顺序
(3)如果我们在运行项目时,上图中current_app和request这两个proxy都是指向上面所说的两个栈的栈顶,如果栈顶有值的情况下,那么就不会出现文章开头的Working outside of application context 错误了
三、问题解决
如上所述,出现这种错误的原因就是_app_ctx_stack这个栈的栈顶没有元素,那么我们可以手动创建一个app将其压入栈中
法一:利用app_context()方法
法二:利用with语句
四、深入理解
在上面提到过,flask的两个上下文对象都实现了四个方法(push,pop,enter,exit)。在python中,实现了enter和exit这两个方法的对象也就是实现了上下文协议,而实现了上下文协议的对象又称作上下文管理器,所以,AppContext和RequestContext这两个对象在flask中都可以称作上下文管理器。那么我们也可以自己实现一个上下文管理器并用with语句测试一下:
更多推荐
所有评论(0)