一、原因
- 对象的应用超出了应用上下文的范围
- 栈_app_ctx_stack为空
二、解决办法
act = app.app_context()
act.push()
# current_app.xxxxx 应用操作
act.pop()
注:pycharm断点调试时,current_app可能会显示LocalProxy:unbound。鼠标放到current_app上会显示正确的内容。
三、深入理解
- Flask上下文
- AppContext:封装了Flask实例对象和一些其他方法和参数。
- RequestContext:封装了Request对象和一些其他方法和参数。
- 都包含push()、pop()、__enter__()、__exit__()方法。
- 编程的过程中使用Flask 和Request对象,要从上下文中获取。
-
出入栈
- 收到一个请求,封装到RequestContext中,检查LocalStack(应用上下文的栈)的栈顶是否为空,如果为空,将AppContext推入(push())到栈(_app_ctx_stack)中,再把RequestContext推入栈(_request_ctx_stack)中。当请求结束时,两个栈中的元素会被弹出(pop())。
- current_app和request 都(LocalProxy)指向应用上下文和请求上下文栈的栈顶元素。返回的是Flask实例对象app和请求对象request。
-
手动入栈、出栈
- act = app.app_context() 获取AppContext
- act.push() 推入_app_ctx_stack栈
- act.pop() 出栈,删除元素
- 手动的出入栈一般应用到离线应用和单元测试。
四、上下文管理器
-
基本概念
- 上下文协议:实现了__enter__()和__exit__()两个方法,即实现了上下文协议;
- 上下文管理器:实现了上下文协议的对象。
- 上下文表达式:with语句,且with必须返回上下文管理器。
- __enter__()
- with demo() as d: d的值是__enter__()方法返回的值
- __exit__()
- __exit__方法返回的是布尔型值。如果with代码块中的内容出现异常,__exit__返回的是False,且会抛出异常。反之返回True。
- __exit__方法需传4个参数,除self的另外三个是exc_type、ext_value、tb。出现异常时,exc_type值为异常的类型;ext_value值为异常的描述;tb值为异常的堆栈信息。
-
应用
- 资源的链接和释放。
- 因此手动出入栈可写为:
with app.app_context() as atc: #atc.xxxx #xxxx