flask核心机制


1

Working outside of application context

 

Working outside of application context.是在flask中出现的经典错误。如下这段代码,就会出现 Working outside of application context.

from flask import Flask, current_app
app = Flask(__name__)a = current_appd = current_app.config['DEBUG']

 

2

Flask的上下文对象

 

Flask有两种Context(上下文),分别是 请求上下文 和应用上下文。

 

RequestContext 请求上下文 包括:

 

  • Request 请求的对象,封装了Http请求(environ)的内容

 

  • Session 根据请求中的cookie,重新载入该访问者相关的会话信息。

 

AppContext 应用上下文 包括:

 

  • g 处理请求时用作临时存储的对象。每次请求都会重设这个变量

 

  • current_app 当前激活程序的程序实例

 

生命周期:

 

  • current_app的生命周期最长,只要当前程序实例还在运行,都不会失效。

 

  • Request和g的生命周期为一次请求期间,当请求处理完成后,生命周期也就完结了。

 

  • Session就是传统意义上的session了。只要它还未失效(用户未关闭浏览器、没有超过设定的失效时间),那么不同的请求会共用同样的session。

     

     

 

 

3

核心机制

 

 

阅读源码文件 globals.py

_request_ctx_stack = LocalStack()_app_ctx_stack = LocalStack()

 

LocalStack是由Werkzeug库提供的一个线程隔离的栈结构,可以将对象推入、弹出, 也可以快速拿到栈顶对象。图为核心机制的原理图,当一个请求进入flask,首先检查_app_ctx_stack中有没有元素,如果栈顶元素是空或者不是当前的对象。那么会先推入AppContext,然后再推入RequestContext。而requext(Local Proxy) current_app(Local Proxy) 始终指向栈顶的元素,如果栈顶是空,就会出现unbound。这就是出现Working outside of application context.的原因。那么,说明只要手动将AppContext推入栈中,就不会出现一样的问题。

 

from flask import Flask, current_app
app = Flask(__name__)# 获取应用上下文ctx = app.app_context()# 将应用上下文推入栈中ctx.push()a = current_appd = current_app.config['DEBUG']# 出栈ctx.pop()

 

运行如下代码,则不会再出现同样问题。那么在视图函数中,为什么不需要手动推入?

 

因为 Flask App 在作为 WSGI Application 运行时,会在每个请求进入的时候将请求上下文推入 _request_ctx_stack 中,而请求上下文一定是 App 上下文之中,所以推入部分的逻辑有这样一条:如果发现 _app_ctx_stack为空,则隐式地推入一个 App 上下文。所以,请求中是不需要手动推上下文入栈的。

 

 

posted on 2019-05-09 15:48  李润声  阅读(683)  评论(0编辑  收藏  举报

导航