执行局部变量:终止全局状态(包括线程局部变量)
xlocal的Python项目详细描述
此模块提供执行局部变量,也称为“xlocal”对象,这些对象实现 “线程局部变量”的一个更受限制的变体。本地执行允许 在每次执行的基础上管理属性的方式类似于 当地人工作:
- 调用的函数无法更改调用函数的绑定
xlocal对象的属性绑定不会泄漏到 上下文管理的代码块,它们不会泄漏到 绿色的。相反,进程全局和所谓的“线程” “locals”不实现上述属性。
让我们看一个基本示例:
# content of example.py from xlocal import xlocal xcurrent = xlocal() def output(): print "hello world", xcurrent.x if __name__ == "__main__": with xcurrent(x=1): output()
如果我们执行这个模块,output()函数将看到 axcurrent.x==1绑定:
$ python example.py hello world 1
下面是详细的情况:xcurrent(x=1)返回一个上下文管理器 设置/重置xcurrent对象的x属性。在剩下的时候 在同一个线程/greenlet中,由with主体触发的所有代码(在本例中 只有output()函数)可以访问xcurrent.x。在外面和- bodyxcurrent.x将引发attributeerror。这也是不允许的 要直接设置xcurrent属性,您必须明确地标记它们 带有WITH语句的生命周期。这意味着调用的代码:
- 无法重新绑定其调用函数的xlocal状态(没有副作用,耶!)
- XLocal状态不会泄漏到WITH上下文之外(生命周期控件)
另一个模块现在可以重用示例代码:
# content of example_call.py import example with example.xcurrent(x=3): example.output()
当运行时…:
$ python example_call.py hello world 3
将导致example.output()函数打印xcurrent.x绑定 在调用with xcurrent(x=3)语句中定义。
其他线程或greenlet永远不会看到这种xcurrent.x绑定;它们甚至可能 设置并读取自己的distincitxcurrent.x对象。这意味着 线程/greenlet可以同时调用一个函数,该函数将始终 请参见特定于执行的x属性。
在调用“处理程序”的框架和库中使用
当调用插件代码或处理程序代码来执行工作时,您不能 想把所有可能需要的州都传出去。而不是使用 全局或线程本地,可以在 处决当地人。下面是一个伪示例:
xcurrent = xlocal() def with_xlocal(func, **kwargs): with xcurrent(**kwargs): func() def handle_request(request): func = gethandler(request) # some user code spawn(with_xlocal(func, request=request))
handle_request将在新的 生成的执行单元(例如,spawn可能映射到 threading.Thread(...).start()或到gevent.spawn(...))。这个 泛型with_xlocalhelper包装处理程序的执行 函数,以便它将看到一个xcurrent.request绑定。多重 派生可以并发执行,xcurrent.request将 在每个请求中携带特定于执行的请求对象。
值得注意的问题
如果一个方法记住了一个执行本地的属性,那么 例如上面的xcurrent.request,那么它将保留对 确切的请求对象,而不是每次执行的对象。如果你想的话 保持每次执行都是本地的,您可以这样做,例如:
Class Renderer: @property def request(self): return xcurrent.request
这意味着呈现器实例将具有本地执行 self.request对象,即使实例的生命周期跨越 执行单位。
另一个问题是,如果生成新的执行单元,它们将不会 隐式继承执行局部变量。相反,你必须包装 生成函数以明确设置执行局部变量,类似于 我们在上面的“调用处理程序”部分所做的。
版权/灵感
此代码基于与Armin Ronacher和其他人的讨论 作为对tweet of mine的响应。它提取并改进了armin的“werzeug.local”模块中的一些思想 还有朋友。
copyright: |
|
---|---|
license: | BSD, see LICENSE for more details. |