Werkzeug源码阅读笔记(三)
这次主要讲下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源码阅读笔记(三)的更多相关文章
- werkzeug源码阅读笔记(二) 下
wsgi.py----第二部分 pop_path_info()函数 先测试一下这个函数的作用: >>> from werkzeug.wsgi import pop_path_info ...
- werkzeug源码阅读笔记(二) 上
因为第一部分是关于初始化的部分的,我就没有发布出来~ wsgi.py----第一部分 在分析这个模块之前, 需要了解一下WSGI, 大致了解了之后再继续~ get_current_url()函数 很明 ...
- Werkzeug源码阅读笔记(四)
今天主要讲一下werkzeug中的routing模块.这个模块是werkzeug中的重点模块,Flask中的路由相关的操作使用的都是这个模块 routing模块的用法 在讲解模块的源码之前,先讲讲这个 ...
- CI框架源码阅读笔记5 基准测试 BenchMark.php
上一篇博客(CI框架源码阅读笔记4 引导文件CodeIgniter.php)中,我们已经看到:CI中核心流程的核心功能都是由不同的组件来完成的.这些组件类似于一个一个单独的模块,不同的模块完成不同的功 ...
- CI框架源码阅读笔记2 一切的入口 index.php
上一节(CI框架源码阅读笔记1 - 环境准备.基本术语和框架流程)中,我们提到了CI框架的基本流程,这里再次贴出流程图,以备参考: 作为CI框架的入口文件,源码阅读,自然由此开始.在源码阅读的过程中, ...
- 源码阅读笔记 - 1 MSVC2015中的std::sort
大约寒假开始的时候我就已经把std::sort的源码阅读完毕并理解其中的做法了,到了寒假结尾,姑且把它写出来 这是我的第一篇源码阅读笔记,以后会发更多的,包括算法和库实现,源码会按照我自己的代码风格格 ...
- libevent源码阅读笔记(一):libevent对epoll的封装
title: libevent源码阅读笔记(一):libevent对epoll的封装 最近开始阅读网络库libevent的源码,阅读源码之前,大致看了张亮写的几篇博文(libevent源码深度剖析 h ...
- jdk源码阅读笔记-LinkedHashMap
Map是Java collection framework 中重要的组成部分,特别是HashMap是在我们在日常的开发的过程中使用的最多的一个集合.但是遗憾的是,存放在HashMap中元素都是无序的, ...
- faster rcnn源码阅读笔记1
自己保存的源码阅读笔记哈 faster rcnn 的主要识别过程(粗略) (开始填坑了): 一张3通道,1600*1600图像输入中,经过特征提取网络,得到100*100*512的feature ma ...
随机推荐
- C#修改 Excel指定单元格的值
/// <summary> /// 将指定字符串写入指定单元格中 /// </summary> /// <param name="data">要 ...
- 实现Jquery触发一事件后,停留5秒,再接着触发下面的事件
这里是一个广告位的Jquery的代码,有两个不同的广告位,一个是中间浮动显示的,显示5秒后自动消失,并限定每天仅出现一次(Cookie实现): //=====================广告位的j ...
- hdu1711Number Sequence
Problem Description Given two sequences of numbers : a[1], a[2], ...... , a[N], and b[1], b[2], .... ...
- BF算法(朴素的模式匹配算法)
#include <stdio.h> #include <stdlib.h> int Index_BF(char S[],char T[])//s为目标串(长串),t为模式串( ...
- switch 与 whille相互套用
一直自以为还比较了解C++,这两天写个小工具结果出现了个bug,查了几个小时.现在才发现我这么水. switch是C++后来推出了,目的在于提高代码结构清晰度. 但是switch与while连用时是有 ...
- 删除数组中等于某个key的所有元素
题目描述: 给定一个数组和一个值,在原地删除与值相同的数字,返回新数组的长度. 这道题目做暴力的想法就是,用一个指针从头到尾遍历,删除哪个元素就把后面的元素统一向前移动一个位置.但是这样的时间复杂度很 ...
- [ZT]图像处理库的比较:OpenCV,FreeImage,CImg,CxImage
1.对OpenCV 的印象:功能十分的强大,而且支持目前先进的图像处理技术,体系十分完善,操作手册很详细,手册首先给大家补计算机视觉的知识,几乎涵盖了近10年内的主流算法: 然后将图像格式和矩阵运算, ...
- MySQL表结构同步工具 mysql-schema-sync
mysql-schema-sync 是一款使用go开发的.跨平台的.绿色无依赖的 MySQL 表结构自动同步工具.用于将线上(其他环境)数据库结构变化同步到测试(本地)环境! 可以解决多人开发,每人都 ...
- jquery ajax提交及请求
jQuery.ajax({ url: dataURL, success: function(results) { var parsedJson = jQuery.parseJSON(results); ...
- Prisma
AI修图艺术:Prisma背后的奇妙算法 | 深度 投递人 itwriter 发布于 2016-07-30 12:47 评论(2) 有712人阅读 原文链接 [收藏] « » 雷锋网按:本文作者系图普 ...