上下文局部¶
您可能会发现,您在每个请求期间都有一些数据,您希望跨函数使用这些数据。您可能希望将它们作为全局数据进行访问,而不是将它们作为参数在每个函数之间传递。然而,在PythonWeb应用程序中使用全局变量并不是线程安全的;不同的工作进程可能会干扰彼此的数据。
在请求过程中,您必须使用上下文局部变量,而不是使用全局变量来存储公共数据。上下文本地是全局定义/导入的,但它包含的数据特定于当前线程、异步任务或greenlet。您不会意外地获取或覆盖其他工作人员的数据。
在Python中存储每个上下文的数据的当前方法是 contextvars
模块。上下文变量按线程、异步任务或greenlet存储数据。这将取代较旧的 threading.local
它只处理线程。
Werkzeug提供了包装纸 ContextVar
以使其更容易使用。
代理对象¶
LocalProxy
允许直接将上下文变量视为对象,而不需要使用和检查 ContextVar.get()
。如果设置了上下文变量,则本地代理的外观和行为将与该变量设置为的对象相似。如果未设置,则会引发 RuntimeError
在大多数操作中都会出现异常。
from contextvars import ContextVar
from werkzeug.local import LocalProxy
_request_var = ContextVar("request")
request = LocalProxy(_request_var)
from werkzeug.wrappers import Request
@Request.application
def app(r):
_request_var.set(r)
check_auth()
...
from werkzeug.exceptions import Unauthorized
def check_auth():
if request.form["username"] != "admin":
raise Unauthorized()
访问 request
将指向每个服务器工作者正在处理的特定请求。你可以治疗 request
就像一个真正的 Request
对象。
bool(proxy)
永远都会回来 False
如果未设置var,则。如果需要直接访问对象而不是代理,可以使用 _get_current_object()
方法。
- class werkzeug.local.LocalProxy(local, name=None, *, unbound_message=None)¶
绑定到上下文本地对象的对象的代理。代理上的所有操作都被转发到绑定对象。如果没有绑定任何对象,则会引发
RuntimeError
都被养大了。- 参数:
local -- 提供代理对象的上下文本地对象。
name -- 代理对象中的该属性。
unbound_message -- 显示上下文本地对象是否解除绑定的错误消息。
代理服务器A
ContextVar
以使其更容易访问。传递一个名称以代理该属性。_request_var = ContextVar("request") request = LocalProxy(_request_var) session = LocalProxy(_request_var, "session")
代理上的属性
Local
命名空间,方法是使用以下属性名称调用本地:data = Local() user = data("user")
代理上的顶端项
LocalStack
打电话给当地人。传递一个名称以代理该属性。app_stack = LocalStack() current_app = app_stack() g = app_stack("g")
传递一个函数以代理该函数的返回值。在被直接支持之前,它以前用于访问本地对象的属性。
session = LocalProxy(lambda: request.session)
__repr__
和__class__
都是代理的,所以repr(x)
和isinstance(x, cls)
将看起来像代理对象。使用issubclass(type(x), LocalProxy)
要检查对象是否为代理,请执行以下操作。repr(user) # <User admin> isinstance(user, User) # True issubclass(type(user), LocalProxy) # True
Changelog
在 2.2.2 版本发生变更:
__wrapped__
在包装对象时设置,而不仅仅是在包装函数时设置,以防止doctest失败。在 2.2 版本发生变更: 可以代理
ContextVar
或LocalStack
直接去吧。在 2.2 版本发生变更: 这个
name
参数可以与任何代理对象一起使用,不仅Local
。在 2.2 版本发生变更: 添加了
unbound_message
参数。在 2.0 版本发生变更: 更新了代理属性和方法以反映当前数据模型。
在 0.6.1 版本发生变更: 类可以使用Callable实例化。
堆栈和命名空间¶
ContextVar
一次存储一个值。您可能会发现需要存储一堆项或具有多个属性的命名空间。可以使用列表或字典来处理这些内容,但将它们用作上下文变量值需要格外小心。Werkzeug提供 LocalStack
它包装了一个列表,并且 Local
这就说明了一个问题。
存在与这些对象相关的一定程度的性能损失。因为列表和词典是可变的, LocalStack
和 Local
需要做额外的工作以确保数据不会在嵌套的上下文之间共享。如果可能,将您的应用程序设计为使用 LocalProxy
直接围绕上下文变量。
- class werkzeug.local.LocalStack(context_var=None)¶
创建一个上下文本地数据堆栈。这包装了一个
ContextVar
包含一个list
价值。与使用单个上下文变量相比,这可能会导致性能损失,因为它必须复制数据以避免在嵌套上下文之间更改列表。
- 参数:
context_var (ContextVar[list[T]] | None) -- 这个
ContextVar
用作此本地数据库的存储。如果没有给出,将创建一个。不是在全局范围内创建的上下文变量可能会干扰垃圾收集。
Changelog
在 2.0 版本发生变更: 用途
ContextVar
而不是定制存储实现。在 0.6.1 版本加入.
- __call__(name=None, *, unbound_message=None)¶
创建
LocalProxy
访问此本地堆栈顶部的。- 参数:
- 返回类型:
- pop()¶
从堆栈中移除顶部的项并将其返回。如果堆栈为空,则返回
None
。- 返回类型:
T | None
- class werkzeug.local.Local(context_var=None)¶
创建上下文本地数据的命名空间。这包装了一个
ContextVar
包含一个dict
价值。与使用单个上下文变量相比,这可能会导致性能损失,因为它必须复制数据以避免在嵌套上下文之间改变字典。
- 参数:
context_var (ContextVar[dict[str, t.Any]] | None) -- 这个
ContextVar
用作此本地数据库的存储。如果没有给出,将创建一个。不是在全局范围内创建的上下文变量可能会干扰垃圾收集。
Changelog
在 2.0 版本发生变更: 用途
ContextVar
而不是定制存储实现。- __call__(name, *, unbound_message=None)¶
创建
LocalProxy
访问此本地命名空间上的属性的。- 参数:
- 返回类型:
发布数据¶
以前的实现 Local
使用的内部数据结构无法在每个上下文结束时自动清除。相反,可以使用以下实用程序来发布数据。
警告
现代实现应该不需要这样做,因为上下文变量中的数据是由Python自动管理的。它暂时被保留是为了兼容,但将来可能会被移除。
- class werkzeug.local.LocalManager(locals=None)¶
管理在一个或多个环境中发布当前上下文的数据
Local
和LocalStack
物体。现代用例不需要这样做,将来可能会删除。
- 参数:
locals (None | (Local | LocalStack | t.Iterable[Local | LocalStack])) -- 要管理的本地人员或本地人员列表。
Changelog
在 2.1 版本发生变更: 这个
ident_func
被移除了。在 0.7 版本发生变更: 这个
ident_func
参数已添加。在 0.6.1 版本发生变更: 这个
release_local()
函数可以用来代替管理器。- cleanup()¶
释放此上下文的本地变量中的数据。在每次请求或使用结束时调用此方法
make_middleware()
。- 返回类型:
None
- make_middleware(app)¶
包装WSGI应用程序,以便在发送请求响应后自动释放本地数据。
- 参数:
app (WSGIApplication) --
- 返回类型:
WSGIApplication
- middleware(func)¶
喜欢
make_middleware()
但用作WSGI应用程序函数的装饰符。@manager.middleware def application(environ, start_response): ...
- 参数:
func (WSGIApplication) --
- 返回类型:
WSGIApplication
- werkzeug.local.release_local(local)¶
中释放当前上下文的数据。
Local
或LocalStack
而不使用LocalManager
。现代用例不需要这样做,将来可能会删除。
Changelog
在 0.6.1 版本加入.
- 参数:
local (Local | LocalStack) --
- 返回类型:
None