这次主要讲下werkzeug中的Local. 源码在werkzeug/local.py

Thread Local

在Python中,状态是保存在对象中。Thread Local是一种特殊的对象,它是对线程隔离的。所谓对线程隔离,是指每一个线程对一个Thread Local对象进行修改,是不会影响到其他线程的。这就好比在工作单位每个人都有一个储物柜,每个人对自己的储物柜存取东西是不会影响到其他人的。这里的储物柜就是Thread Local.

获得一个Thread Local很简单,只需要对线程执行Local():threading.Local()

werkzeug的源码中,Local()类的实现比较简单,只是定义了几个特殊函数。文件在werkzeug/local.py

在该文件中,还定义了release_local(local)方法,用来释放local对象. 同时,在Local()类中实现了__release_local__()函数,它包裹了release_local(local)函数,调用__release_local__()可以释放当前Local对象

LocalStack

在werkzeug中同时实现了LocalStack这个类,它包含了Local()类的实例,实现了Local的栈结构,以下是重要部分的代码:

class LocalStack(object):
def __init__(self):
self._local = Local() #LocalStack中有个Local类的对象 def __release_local__(self): #定义释放当前Local对象的方法
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):
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):
try:
return self._local.stack[-1]
except (AttributeError, IndexError):
return None

所有对该对象的修改,只对本线程可见

LocalProxy

在werkzeug中还定义了本地代理。LocalProxy是典型的代理模式的实现。它在构造的时候接受一个callable的参数(实现了__call__()方法的类,一个函数等),这个参数被调用后的返回值本身是一个Thread Local对象。对一个LocalProxy对象的所有操作都会转发到那个callable参数返回的Thread Local对象上。

这是LocalProxy的初始化函数:

def __init__(self, local, name=None):
object.__setattr__(self, '_LocalProxy__local', local)
object.__setattr__(self, '__name__', name)

可以看到,该函数中有个local参数,这个参数就是callable参数。

下面是Local类中的__call__()函数

def __call__(self, proxy):
"""Create a proxy for a name."""
return LocalProxy(self, proxy)

比如执行:

l = Local()
request = l('request')

这时候就会调用__call__()函数,request = l('request')相当于执行:

request = LocalProxy(l, 'request')

这时候request就是一个LocalProxy对象,自动调用初始化函数,该对象有两个元素:_LocalProxy__local(等于l)和__name__(等于'request')

所以,对request的操作会返还给l进行实际操作

同时注意到LocalStack类也实现了__call__()函数,同样可以当做local参数.

LocalStack中的__call__函数:

def __call__(self):
def _lookup():
rv = self.top
if rv is None:
raise RuntimeError('object unbound')
return rv
return LocalProxy(_lookup)

执行:

_response_local = LocalStack()
response = _response_local()

这时候response就是一个LocalProxy,自动调用初始化函数,该对象有两个元素:_LocalProxy__local(等于_lookup函数)和__name__(等于None)

LocalProxy类中,还实现了一个重要的方法:_get_current_object():

def _get_current_object(self):
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__)

这个方法的作用是获得该LocalProxy对象背后的真正的对象

LocalManager

在该文件中,还实现了LocalManager这个类. 因为Local对象不能管理自身,所以可能需要一个LocalManager对象,可以把多个Local对象传给LocalManager对象,该对象的每一次清理操作就会清理掉当前上下文中的Local对象

具体的类方法很简单,就不一一赘述了

Werkzeug源码阅读笔记(三)的更多相关文章

  1. werkzeug源码阅读笔记(二) 下

    wsgi.py----第二部分 pop_path_info()函数 先测试一下这个函数的作用: >>> from werkzeug.wsgi import pop_path_info ...

  2. werkzeug源码阅读笔记(二) 上

    因为第一部分是关于初始化的部分的,我就没有发布出来~ wsgi.py----第一部分 在分析这个模块之前, 需要了解一下WSGI, 大致了解了之后再继续~ get_current_url()函数 很明 ...

  3. Werkzeug源码阅读笔记(四)

    今天主要讲一下werkzeug中的routing模块.这个模块是werkzeug中的重点模块,Flask中的路由相关的操作使用的都是这个模块 routing模块的用法 在讲解模块的源码之前,先讲讲这个 ...

  4. CI框架源码阅读笔记5 基准测试 BenchMark.php

    上一篇博客(CI框架源码阅读笔记4 引导文件CodeIgniter.php)中,我们已经看到:CI中核心流程的核心功能都是由不同的组件来完成的.这些组件类似于一个一个单独的模块,不同的模块完成不同的功 ...

  5. CI框架源码阅读笔记2 一切的入口 index.php

    上一节(CI框架源码阅读笔记1 - 环境准备.基本术语和框架流程)中,我们提到了CI框架的基本流程,这里再次贴出流程图,以备参考: 作为CI框架的入口文件,源码阅读,自然由此开始.在源码阅读的过程中, ...

  6. 源码阅读笔记 - 1 MSVC2015中的std::sort

    大约寒假开始的时候我就已经把std::sort的源码阅读完毕并理解其中的做法了,到了寒假结尾,姑且把它写出来 这是我的第一篇源码阅读笔记,以后会发更多的,包括算法和库实现,源码会按照我自己的代码风格格 ...

  7. libevent源码阅读笔记(一):libevent对epoll的封装

    title: libevent源码阅读笔记(一):libevent对epoll的封装 最近开始阅读网络库libevent的源码,阅读源码之前,大致看了张亮写的几篇博文(libevent源码深度剖析 h ...

  8. jdk源码阅读笔记-LinkedHashMap

    Map是Java collection framework 中重要的组成部分,特别是HashMap是在我们在日常的开发的过程中使用的最多的一个集合.但是遗憾的是,存放在HashMap中元素都是无序的, ...

  9. faster rcnn源码阅读笔记1

    自己保存的源码阅读笔记哈 faster rcnn 的主要识别过程(粗略) (开始填坑了): 一张3通道,1600*1600图像输入中,经过特征提取网络,得到100*100*512的feature ma ...

随机推荐

  1. Android Studio无法关联Api23源码-提示Souces for android api 23 platform not found

    最近升级了As,然后忽然就关联不上源码了,很不方便,找个Activity的源码都只有outline没有解释,还提示这个错误: Decompiled .class file, bytecode vers ...

  2. [Linked List]Linked List Cycle,Linked List Cycle II

    一.Linked List Cycle Total Accepted: 85115 Total Submissions: 232388 Difficulty: Medium Given a linke ...

  3. C++ extern "C",C与C++的区别

    1. C++保留了一部分过程式语言的特点,因而它可以定义不属于任何类的全局变量和函数.但是,C++毕竟是一种面向对象的程序设计语言,为了支持函数的重载,C++对全局函数的处理方式与C有明显的不同. 2 ...

  4. 在非MVC环境下使用 Razor引擎

    Razor引擎下载地址: http://github.com/Antaris/RazorEngine 解析Model: string template = "Hello @Model.Nam ...

  5. Python urllib和urllib2模块学习(一)

    (参考资料:现代魔法学院 http://www.nowamagic.net/academy/detail/1302803) Python标准库中有许多实用的工具类,但是在具体使用时,标准库文档上对使用 ...

  6. Spring中常用的hql查询方法(getHibernateTemplate())

    一.find(String queryString); 示例:getHibernateTemplate().find("from bean.User"); 返回所有User对象 二 ...

  7. 计算机图形学--旋转变换(java)

    import java.awt.Color; import java.awt.Frame; import java.awt.Graphics; import java.awt.event.Window ...

  8. ueditor 编辑器的配置 实现上传图片---附效果图

    由于项目需要,最近使用了ueditor,实现了图片上传功能,在此分享一下遇到的一些问题. 项目使用net+mvc框架搭建,则选择的是NET版本ueditor 编辑器(可去百度官网下载), 下载完成导入 ...

  9. C语言入门(19)——C语言的编码风格

    代码风格好不好就像字写得好不好看一样,如果一个公司招聘秘书,肯定不要字写得难看的,同理,代码风格糟糕的程序员肯定也是不称职的.虽然编译器不会挑剔难看的代码,照样能编译通过,但是和你一个团队进行协作的其 ...

  10. Struts2六、为应用指定多个配置文件

    为了使用Struts.xml更简洁,更利于维护,我们可以把Struts.xml要配置的Action信息分类别放在其他的XML文件中,使用include在struts.xml中加载这些文件: 将Web. ...