TOP

python语言线程标准库threading.local源码解读(一)
2019-11-15 18:42:13 】 浏览:19
Tags:python 语言 线程 标准 threading.local 源码 解读

本段源码可以学习的地方:

1. 考虑到效率问题,可以通过上下文的机制,在属性被访问的时候临时构建;

2. 可以重写一些魔术方法,比如 __new__ 方法,在调用 object.__new__(cls) 前后进行属性的一些小设置;

3. 在本库中使用的重写魔术方法,上下文这两种基础之上,我们可以想到函数装饰器,类装饰器,异常捕获,以及两种上下文的结构;

灵活运用这些手法,可以让我们在代码架构上更上一层,能够更加省时省力。

  1 from weakref import ref  # ref用在了构造大字典元素元组的第一个位置即 (ref(Thread), 线程字典)
  2 from contextlib import contextmanager  # 上下文管理,用来确保__dict__属性的存在
  3 from threading import current_thread, RLock
  4 __all__ = ["local"]
  5 
  6 class _localimpl:  # local()._local__impl = _localimpl()  # local()实例的属性_local__impl就是这个类的实例
  7     """一个管理线程字典的类"""
  8     __slots__ = 'key', 'dicts', 'localargs', 'locallock', '__weakref__'  # _local__impl有这么多属性
  9 
 10     def __init__(self):
 11         # 这个self.key是用在线程对象的字典中的key
 12         # self.key使用的一个字符串,这样既能运行的快,
 13         # 但是通过'_threading_local._localimpl.' + str(id(self)也能保证不会冲突别的属性
 14 
 15         self.key = '_threading_local._localimpl.' + str(id(self))
 16         #
 17         self.dicts = {}  # 大字典
 18         # 格式是: { id(线程1):(ref(Thread), 线程1自身的字典), id(线程2):(ref(Thread), 线程2自身的字典), ... }
 19 
 20     def get_dict(self):  # 从大字典中拿(ref(Thread), 线程字典), 然后取线程字典
 21         thread = current_thread()
 22         return self.dicts[id(thread)][1]
 23 
 24     def create_dict(self):  # 为当前线程创建一个线程字典,就是(ref(Thread), 线程字典)[1],即元组的第二部分
 25         localdict = {}
 26         key = self.key  # key使用'_threading_local._localimpl.' + str(id(self)
 27         thread = current_thread()  # 当前线程
 28         idt = id(thread)  # 当前线程的id
 29         def local_deleted(_, key=key):  # 这个函数不看  pass
 30             # When the localimpl is deleted, remove the thread attribute.
 31             thread = wrthread()
 32             if thread is not None:
 33                 del thread.__dict__[key]
 34         def thread_deleted(_, idt=idt):  # 这个函数不看 pass
 35             # When the thread is deleted, remove the local dict.
 36             # Note that this is suboptimal if the thread object gets
 37             # caught in a reference loop. We would like to be called
 38             # as soon as the OS-level thread ends instead.
 39             local = wrlocal()
 40             if local is not None:
 41                 dct = local.dicts.pop(idt)
 42         wrlocal = ref(self, local_deleted)
 43         wrthread = ref(thread, thread_deleted)  # 大字典中每一个线程对应的元素的第一个位置: (ref(Thread), 小字典)
 44         thread.__dict__[key] = wrlocal
 45         self.dicts[idt] = wrthread, localdict  # 在大字典中构造: id(thread) : (ref(Thread), 小字典)
 46         return localdict
 47 
 48 
 49 @contextmanager
 50 def _patch(self):
 51     impl = object.__getattribute__(self, '_local__impl')  # 此时的self是local(), 拿local()._local__impl
 52     try:
 53         dct = impl.get_dict()   # 然后从拿到的local()._local__impl调用线程字典管理类的local()._local__impl.get_dict()方法
 54                                 # 从20行到22这个get_dict()方法的定义可以看出来,拿不到会报KeyError的
 55 
 56     except KeyError:  # 如果拿不到报 KeyError之后捕捉
 57         dct = impl.create_dict()  # 然后再通过线程字典管理类临时创建一个
 58         args, kw = impl.localargs  # 这个时候把拿到
 59         self.__init__(*args, **kw)
 60     with impl.locallock:  # 通过上下文的方式上锁
 61         object.__setattr__(self, '__dict__', dct)  # 给local() 实例增加__dict__属性,这个属性指向大字典中value元组的第二个元素,即线程小字典
 62         yield  # 到目前为止,local()类的两个属性都构造完成
 63 
 64 
 65 class local:  # local类
 66     __slots__ = '_local__impl', '__dict__'  # local类有两个属性可以访问
 67 
 68     def __new__(cls, *args, **kw):
 69         if (args or kw) and (cls.__init__ is object.__init__):  # pass不看
 70             raise TypeError("Initialization arguments are not supported")
 71         self = object.__new__(cls)  # pass不看
 72         impl = _localimpl()  # _local_impl属性对应的是_localimpl类的实例
 73         impl.localargs = (args, kw)  # _local_impl属性即_localimpl类的实例 的 localargs属性是一个元组
 74         impl.locallock = RLock()  # pass 不看
 75         object.__setattr__(  
		
python语言线程标准库threading.local源码解读(一) https://www.cppentry.com/bencandy.php?fid=97&id=266160

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇设计模式学习笔记 下一篇分布式事务之基本概念