werkzeug之Local解析
来源:互联网 发布:mac 如何恢复苹果系统 编辑:程序博客网 时间:2024/05/20 08:22
werkzeug库的local模块实现了类似java中的线程变量,该模块有4个类Local,LocalStack,LocalManager,LocalProxy,我们一一分析
Local
class Local(object): __slots__ = ('__storage__', '__ident_func__') def __init__(self): object.__setattr__(self, '__storage__', {}) object.__setattr__(self, '__ident_func__', get_ident) def __iter__(self): return iter(self.__storage__.items()) def __call__(self, proxy): """Create a proxy for a name.""" return LocalProxy(self, proxy) def __release_local__(self): self.__storage__.pop(self.__ident_func__(), None) def __getattr__(self, name): try: return self.__storage__[self.__ident_func__()][name] except KeyError: raise AttributeError(name) def __setattr__(self, name, value): ident = self.__ident_func__() storage = self.__storage__ try: storage[ident][name] = value except KeyError: storage[ident] = {name: value} def __delattr__(self, name): try: del self.__storage__[self.__ident_func__()][name] except KeyError: raise AttributeError(name)该类有两个关键参数:'__storage__', '__ident_func__',其中'__storage__'初始化为一个空字典:{},'__ident_func__'初始化为get_ident,get_iden()函数返回一个协程/线程ID。
从__setattr__方法实现可以看出,给Local添加属性时,以协程/线程ID为第一级key,以属性名称为第二级key来保存值。下面做个试验以加深理解:
>>> l = Local()>>> l.stack = 'request'>>> l.__storage__{8168: {'stack': 'request'}}>>>
LocalStack
class LocalStack(object): def __init__(self): self._local = Local() def __release_local__(self): self._local.__release_local__() def _get__ident_func__(self): return self._local.__ident_func__ def _set__ident_func__(self, value): object.__setattr__(self._local, '__ident_func__', value) __ident_func__ = property(_get__ident_func__, _set__ident_func__) del _get__ident_func__, _set__ident_func__ def __call__(self): def _lookup(): rv = self.top if rv is None: raise RuntimeError('object unbound') return rv return LocalProxy(_lookup) def push(self, obj): """Pushes a new item to the stack""" rv = getattr(self._local, 'stack', None) if rv is None: self._local.stack = rv = [] rv.append(obj) return rv def pop(self): """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): """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
LocalStack类的内部以Local为基础实现的,只不过对外提供了push,pop方法类似于栈结构。LocalStack将新增的属性及其值添加到Local的stack属性中,并且stack类型是列表当然,从前面实验中可以看出,Local的stack属性最终是存放在__storage__字典里面,并且以协程/线程ID隔离开。
>>> ls = LocalStack()>>> ls.push(10)[10]>>> ls.push('test')[10, 'test']>>> ls._local.__storage__{5948: {'stack': [10, 'test']}}>>> ls.top'test'>>>
LocalProxy
class LocalProxy(object): __slots__ = ('__local', '__dict__', '__name__', '__wrapped__') def __init__(self, local, name=None): object.__setattr__(self, '_LocalProxy__local', local) object.__setattr__(self, '__name__', name) if callable(local) and not hasattr(local, '__release_local__'): # "local" is a callable that is not an instance of Local or # LocalManager: mark it as a wrapped function. object.__setattr__(self, '__wrapped__', local) def _get_current_object(self): """Return the current object. This is useful if you want the real object behind the proxy at a time for performance reasons or because you want to pass the object into a different context. """ if not hasattr(self.__local, '__release_local__'): return self.__local() try: return getattr(self.__local, self.__name__) except AttributeError: raise RuntimeError('no object bound to %s' % self.__name__) @property def __dict__(self): try: return self._get_current_object().__dict__ except RuntimeError: raise AttributeError('__dict__') def __repr__(self): try: obj = self._get_current_object() except RuntimeError: return '<%s unbound>' % self.__class__.__name__ return repr(obj) def __bool__(self): try: return bool(self._get_current_object()) except RuntimeError: return False def __unicode__(self): try: return unicode(self._get_current_object()) # noqa except RuntimeError: return repr(self) def __dir__(self): try: return dir(self._get_current_object()) except RuntimeError: return [] def __getattr__(self, name): if name == '__members__': return dir(self._get_current_object()) return getattr(self._get_current_object(), name) def __setitem__(self, key, value): self._get_current_object()[key] = value def __delitem__(self, key): del self._get_current_object()[key] if PY2: __getslice__ = lambda x, i, j: x._get_current_object()[i:j] def __setslice__(self, i, j, seq): self._get_current_object()[i:j] = seq def __delslice__(self, i, j): del self._get_current_object()[i:j] __setattr__ = lambda x, n, v: setattr(x._get_current_object(), n, v) __delattr__ = lambda x, n: delattr(x._get_current_object(), n)LocalProxy是对具体对象的代理
阅读全文
0 0
- werkzeug之Local解析
- Werkzeug 之URL 路由
- Werkzeug 之数据结构解读不可变类
- Flask学习记录之使用Werkzeug散列密码
- ss-libev 源码解析local篇(5):ss-local之remote_send_cb
- ss-libev 源码解析local篇(4): server_recv_cb之STAGE_STREAM
- Werkzeug教程
- wsgi-werkzeug
- Werkzeug简介
- Werkzeug教程
- JAVA工具类,Local解析
- ss-libev 源码解析local篇(3): server_recv_cb之SNI和STAGE_PARSE
- charles之map local
- python web apps -werkzeug
- werkzeug-Context Locals
- Werkzeug学习笔记
- Local System/ Local service /network service 权限解析
- android.mk中常见local变量解析
- JVM调优魔法棒-Java VisualVM
- I NEED A OFFER!
- 使程序在Linux下后台运行 (关掉终端继续让程序运行的方法)
- 按键精灵WQM,怎么重复执行某一脚本?
- 51nod 1276 岛屿的数量 离线算法乱搞
- werkzeug之Local解析
- BeautifuSoup
- [Muduo网络库源码分析] (6) base/Mutex.h_互斥锁操作
- Java中的反射机制
- 对新分配的磁盘空间进行磁盘配置
- CAD编辑技巧之PDF转DWG和DWG图纸的编辑
- ADC中的ABC:理解ADC误差对系统性能的影响(转载)
- [HNOI2002]营业额统计
- Apache Storm 的安装、配置及入门基础(一)