python学习Flask首页投稿(暂停使用,暂停投稿)

Flask的核心机制!关于请求处理流程和上下文

2016-09-05  本文已影响4267人  ayawaya

学习一样东西不能只停留在表面,我们要探索其中的细节,学习作者的编程思想,这样才能更进一步。

关于WSGI

WSGI(全称Web Server Gateway Interface),是为 Python 语言定义的Web服务器Web应用程序之间的一种简单而通用的接口,它封装了接受HTTP请求解析HTTP请求发送HTTP响应等等的这些底层的代码和操作,使开发者可以高效的编写Web应用。

一个简单的使用WSGI的App例子:

def application(environ, start_response): 
    start_response('200 OK', [('Content-Type', 'text/html')]) 
    return [b'<h1>Hello, I Am WSGI!</h1>']
WSGI Server 和 App交互图

Flask的上下文对象

Flask有两种Context(上下文),分别是

生命周期:

Flask处理流程

Flask处理请求流程
# 声明对象
# LocalStack  LocalProxy 都由Werkzeug提供
# 我们不深究他的细节,那又是另外一个故事了,我们只需知道他的作用就行了
# LocalStack 是栈结构,可以将对象推入、弹出
# 也可以快速拿到栈顶对象。当然,所有的修改都只在本线程可见。
_request_ctx_stack = LocalStack()
_app_ctx_stack = LocalStack()
# 如果调用一个LocalStack实例, 能返回一个 LocalProxy 对象
# 这个对象始终指向 这个LocalStack实例的栈顶元素。
# 如果栈顶元素不存在,访问这个 LocalProxy 的时候会抛出 RuntimeError异常
# LocalProxy对象你只需暂时理解为栈里面的元素即可了
current_app = LocalProxy(_find_app)
request = LocalProxy(partial(_lookup_req_object, 'request'))
session = LocalProxy(partial(_lookup_req_object, 'session'))
g = LocalProxy(partial(_lookup_app_object, 'g'))
# RequestContext
class RequestContext(object):
    def __init__(self, app, environ, request=None):    
        self.app = app    
        if request is None:        
                request = app.request_class(environ)    
        self.request = request    
        self.url_adapter = app.create_url_adapter(self.request)    
        self.flashes = None    
        self.session = None
#AppContext
class AppContext(object):
    def __init__(self, app):    
        self.app = app    
        self.url_adapter = app.create_url_adapter(None)    
        self.g = app.app_ctx_globals_class()    
        self._refcnt = 0

这里需要注意的是,RequestContext在初始化的时候,当前Flask的实例作为参数被传进来。虽然每次的请求处理都会创建一个RequestContext对象,但是每一次传入的app参数却是同一个。通过这个机制,可以使得:

由同一个Flask实例所创建的RequestContext,其成员变量app都是同一个Flask实例对象 。实现了多个RequestContext对应同一个current_app 的目的。

class RequestContext(object):
    def push(self):   
        ....
        _app_ctx_stack.push(self)   
        appcontext_pushed.send(self.app)

AppContext对象push进_app_ctx_stack里面。在这次请求期间,访问g对象将指向这个栈的栈顶元素

class AppContext(object):
    def push(self):   
        ....
        _request_ctx_stack.push(self)

最后附上Flask处理请求的wsgi_app函数

# environ: WSGI Server封装的HTTP请求信息
# start_response: WSGI Server提供的函数,调用可以发送状态码和HTTP报文头
def wsgi_app(self, environ, start_response):
    # 根据environ创建上下文
    ctx = self.request_context(environ)
    # 把当前的request context,app context绑定到当前的context
    ctx.push()
    error = None
    try:
        try:
            #根据请求的URL,分发请求,经过视图函数处理后返回响应对象
            response = self.full_dispatch_request()    
        except Exception as e:        
            error = e        
            response = self.make_response(self.handle_exception(e))   
        return response(environ, start_response)
    finally:   
        if self.should_ignore_error(error):        
          error = None    
       # 最后出栈
        ctx.auto_pop(error)

参考资料
汇智网:Flask框架-上下文对象 :Flask核心机制

上一篇下一篇

猜你喜欢

热点阅读