flask源码剖析之上下文全局变量
flask有四个线程级的全局变量,两个是程序上下文变量:current_app和g,另外两个是请求上下文变量:request和session.
这四个变量只有从flask.globals中导入才可以使用,即
from flask import current_app
from flask import g
from flask import request
from flask import session
但是使用不意味着有效,要想有效,导入后还要再push程序上下文变量和请求上下文变量:
1)利用flask.app中的app.app_context()或app.request_context()方法建立AppContext(app)实例或RequestContext(...)实例;
app_ctx = app.app_context()
request_ctx = app.request_context(...)
-
def app_context(self):
-
"""Binds the application only. For as long as the application is bound
-
to the current context the :data:`flask.current_app` points to that
-
application. An application context is automatically created when a
-
request context is pushed if necessary.
-
Example usage::
-
with app.app_context():
-
...
-
.. versionadded:: 0.9
-
"""
-
return AppContext(self)
-
def request_context(self, environ):
-
"""Creates a :class:`~flask.ctx.RequestContext` from the given
-
environment and binds it to the current context. This must be used in
-
combination with the `with` statement because the request is only bound
-
to the current context for the duration of the `with` block.
-
Example usage::
-
with app.request_context(environ):
-
do_something_with(request)
-
The object returned can also be used without the `with` statement
-
which is useful for working in the shell. The example above is
-
doing exactly the same as this code::
-
ctx = app.request_context(environ)
-
ctx.push()
-
try:
-
do_something_with(request)
-
finally:
-
ctx.pop()
-
.. versionchanged:: 0.3
-
Added support for non-with statement usage and `with` statement
-
is now passed the ctx object.
-
:param environ: a WSGI environment
-
"""
-
return RequestContext(self, environ)
2)调用1)中建立的实例相应的push()方法——flask.ctx中;
app_ctx.push( )
or request_ctx.push( ) ???这个好像不需要???P12
确实不需要,因为这是系统自动帮我们完成的!!!!具体参见文章Flask request,g,session的实现原理
-
class AppContext(object):
-
"""The application context binds an application object implicitly
-
to the current thread or greenlet, similar to how the
-
:class:`RequestContext` binds request information. The application
-
context is also implicitly created if a request context is created
-
but the application is not on top of the individual application
-
context.
-
"""
-
def __init__(self, app):
-
self.app = app
-
self.url_adapter = app.create_url_adapter(None)
-
self.g = app.app_ctx_globals_class()
-
# Like request context, app contexts can be pushed multiple times
-
# but there a basic "refcount" is enough to track them.
-
self._refcnt = 0
-
def push(self):
-
"""Binds the app context to the current context."""
-
self._refcnt += 1
-
_app_ctx_stack.push(self)
-
appcontext_pushed.send(self.app)
-
......
3)2)中的push()方法实际上就是利用LocalStack()的实例_app_ctx_stack或_request_ctx_stack的push()方法——入栈。因此我们可以使用flask创建n个web app,而不会错乱。
一个web app有很多个request和session信息,使用_request_ctx_stack保存。
-
# -*- coding: utf-8 -*-
-
"""
-
flask.globals
-
~~~~~~~~~~~~~
-
Defines all the global objects that are proxies to the current
-
active context.
-
:copyright: (c) 2011 by Armin Ronacher.
-
:license: BSD, see LICENSE for more details.
-
"""
-
from functools import partial
-
from werkzeug.local import LocalStack, LocalProxy
-
def _lookup_req_object(name):
-
top = _request_ctx_stack.top
-
if top is None:
-
raise RuntimeError('working outside of request context')
-
return getattr(top, name)
-
def _lookup_app_object(name):
-
top = _app_ctx_stack.top
-
if top is None:
-
raise RuntimeError('working outside of application context')
-
return getattr(top, name)
-
def _find_app():
-
top = _app_ctx_stack.top
-
if top is None:
-
raise RuntimeError('working outside of application context')
-
return top.app
-
# context locals
-
_request_ctx_stack = LocalStack()
-
_app_ctx_stack = LocalStack()
-
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'))
4)因此,所谓的app_ctx.push()实质上是落实在LocalStack().push()即_app_ctx_stack.push()之上的!
可参考文章Flask request,g,session的实现原理
出处:https://blog.****.net/LANGQING12345/article/details/46740551