Flask 源码剖析
偏函数 partial
- 对普通函数进行封装, 主要功能是把一个函数的部分参数给固定住
from functools import partial
def add(a, b):
return a*b
d1 = add(4,5)
print(d1)
new_d1 = partial(add,4)
print(new_d1)
print(new_d1(5))
Local对象维护栈
- 根据线程id/协程id , 维护一个存储空间 . 以字典形式
- 结构: {"线程/协程id":{"_storage":[ctx(request/session)]}}
try:
from greenlet import getcurrent as _get_ident
except ImportError:
from threading import get_ident as _get_ident
class Local:
__slots__ = ("_storage",)
def __init__(self) -> None:
object.__setattr__(self, "_storage", ContextVar("local_storage"))
def __iter__(self) -> t.Iterator[t.Tuple[int, t.Any]]:
return iter(self._storage.get({}).items())
def __call__(self, proxy: str) -> "LocalProxy":
"""Create a proxy for a name."""
return LocalProxy(self, proxy)
def __release_local__(self) -> None:
__release_local__(self._storage)
def __getattr__(self, name: str) -> t.Any:
values = self._storage.get({})
try:
return values[name]
except KeyError:
raise AttributeError(name) from None
def __setattr__(self, name: str, value: t.Any) -> None:
values = self._storage.get({}).copy()
values[name] = value
self._storage.set(values)
def __delattr__(self, name: str) -> None:
values = self._storage.get({}).copy()
try:
del values[name]
self._storage.set(values)
except KeyError:
raise AttributeError(name) from None
LocalStack对象栈
class LocalStack:
def __init__(self) -> None:
self._local = Local()
def __release_local__(self) -> None:
self._local.__release_local__()
def __call__(self) -> "LocalProxy":
def _lookup() -> t.Any:
rv = self.top
if rv is None:
raise RuntimeError("object unbound")
return rv
return LocalProxy(_lookup)
def push(self, obj: t.Any) -> t.List[t.Any]:
"""Pushes a new item to the stack"""
rv = getattr(self._local, "stack", []).copy()
rv.append(obj)
self._local.stack = rv
return rv
def pop(self) -> t.Any:
"""Removes the topmost item from the stack, will return the
old value or `None` if the stack was already empty.
"""
stack = getattr(self._local, "stack", None)
if stack is None:
return None
elif len(stack) == 1:
release_local(self._local)
return stack[-1]
else:
return stack.pop()
@property
def top(self) -> t.Any:
"""The topmost item on the stack. If the stack is empty,
`None` is returned.
"""
try:
return self._local.stack[-1]
except (AttributeError, IndexError):
return None
RequestContext , AppContext对象
- RequestContext 请求上下文对象
- 接收到请求后,第一步创建请求上下文 RequestContext 对象
- request 存储着几乎所有的请求数据信息, 当请求处理完成后被销毁
- session 字典容器,当请求处理完成后被销毁
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
self._implicit_app_ctx_stack = []
self.preserved = False
self._preserved_exc = None
self._after_request_functions = []
self.match_request()
- AppContext 应用上下文对象
- current_app 存在于应用上下文活跃期间,会在请求处理完成后,随着应用上下文销毁而销毁
- g 请求期间管理资源 , {}
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()
flask上下文管理机制
1. 当用户请求到来之后,flask内部会创建两个对象:
ctx = ReqeustContext(),内部封装request/sesion
app_ctx = AppContext(),内部封装app/g
2. 然后会将此对象通过各自的LocalStack对象:
_request_ctx_stack = LocalStack()
_app_ctx_stack = LocalStack()
将各自的对象添加到local中.
3.
Local是一个特殊结构,他可以为每个线程(协程)维护一个空间进行存取数据.
LocalStack的作用是将Local中维护成一个栈.
storage结构:
storage = {
1212:{stack:[ctx,]}
}
storage = {
1212:{stack:[app_ctx,]}
}
4. 视图函数如果想要获取:request/session/app/g,只需要导入即可,
导入的本质是去各自storage中获取各自的对象,并调用封装其内部:request/session/app/g. (获取栈顶的数据top)
5. 请求处理完毕,将各自storage中存储的数据进行销毁.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?