flask 上下文的实现

引言

本文主要梳理了flask的current_app, request, session, g的实现原理python

源码说明

本文使用flask 0.5 版本flask

application context 和request context

flask有两个context: application contextrequest contextsession

application context request context
current_app request
g session

这里须要通俗地解释一下application contextrequest contextapp

  1. application 指的就是当你调用app = Flask(__name__)建立的这个对象app函数

  2. request 指的是每次http请求发生时,WSGI server(好比gunicorn)调用Flask.__call__()以后,在Flask对象内部建立的Request对象;spa

  3. application 表示用于响应WSGI请求的应用自己,request 表示每次http请求;code

  4. application的生命周期大于request,一个application存活期间,可能发生屡次http请求,因此,也就会有多个requestserver

下面经过源码了解一下 flask 如何实现这两种context:对象

# 代码摘选自flask 0.5 中的ctx.py文件, 进行了部分删减
class _RequestContext(object):
    
    def __init__(self, app, environ):
        self.app = app
        self.request = app.request_class(environ)
        self.session = app.open_session(self.request)
        self.g = _RequestGlobals()

flask 使用_RequestContext的代码以下:生命周期

class Flask(object):

    def request_context(self, environ):
        return _RequestContext(self, environ)

Flask类中,每次请求都会调用这个request_context函数。这个函数则会建立一个_RequestContext对象。

值得注意的是:这个对象在建立时,将Flask实例的自己做为实参传入_RequestContext自身,所以,
self.app = Flask()

因此,虽然每次http请求都会建立一个_RequestContext对象,可是,每次建立的时候都会将同一个Flask对象传入该对象的app成员变量,使得:

由同一个Flask对象响应的请求所建立的_RequestContext对象的app成员变量都共享同一个application

经过在Flask对象中建立_RequestContext对象,并将Flask自身做为参数传入_RequestContext对象的方式,实现了多个request context对应一个application context 的目的。

接下来,看self.request = app.request_class(environ)这句。
因为app成员变量就是app = Flask(__name__)这个对象,因此,app.request_class就是Flask.request_class
Flask类的定义中:

request_class = Request # Request 是一个类,定义以下:

class Request(RequestBase):
    ...

因此:
self.request = app.request_class(environ)其实是建立了一个Request对象。
因为,一个http请求对应一个_RequestContext对象的建立,而每一个_RequestContext对象的建立对应一个Request对象的建立,因此,每一个http请求对应一个Request对象。

到这里想必已经很清楚了:

application 就是指app = Flask(__name__)对象
request 就是对应每次http 请求建立的Request对象
flask经过_RequestContextappRequest关联起来

总结

  1. app = Flask(__name__)建立了application, 这个application对应的上下文,就是application context

  2. Flask每响应一个http请求,就会建立一个Request对象,这个request对象对应的上下文,就是request context

相关文章
相关标签/搜索