fastapi中的请求上下文
背景
fastapi专注于异步、中间件和依赖项的处理,无法在任意地方使用请求上下文。而Flask中,较为明显的优点,便是可以随处使用请求上下文还有对象g。
构造g对象
-
原理:基于
contextvars来管理上下文 -
代码:
点击查看代码
from contextvars import ContextVar, Token from typing import Any, Dict from starlette.types import ASGIApp, Receive, Scope, Send class Globals: __slots__ = ("_vars", "_reset_tokens") _vars: Dict[str, ContextVar] _reset_tokens: Dict[str, Token] def __init__(self) -> None: object.__setattr__(self, "_vars", {}) object.__setattr__(self, "_reset_tokens", {}) def reset(self) -> None: for _name, var in self._vars.items(): try: var.reset(self._reset_tokens[_name]) # ValueError will be thrown if the reset() happens in # a different context compared to the original set(). # Then just set to None for this new context. except ValueError: var.set(None) def _ensure_var(self, item: str) -> None: if item not in self._vars: self._vars[item] = ContextVar(f"globals:{item}", default=None) self._reset_tokens[item] = self._vars[item].set(None) def __getattr__(self, item: str) -> Any: return self._vars[item].get() def __setattr__(self, item: str, value: Any) -> None: self._ensure_var(item) self._vars[item].set(value) class GlobalsMiddleware: def __init__(self, app: ASGIApp) -> None: self.app = app async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: if scope["type"] != "lifespan": g.reset() await self.app(scope, receive, send) g = Globals()
【注】:代码来源
遇上方知有

浙公网安备 33010602011771号