python語(yǔ)言線程標(biāo)準(zhǔn)庫(kù)threading.local有什么用-創(chuàng)新互聯(lián)

小編給大家分享一下python語(yǔ)言線程標(biāo)準(zhǔn)庫(kù)threading.local有什么用,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

站在用戶的角度思考問題,與客戶深入溝通,找到敘州網(wǎng)站設(shè)計(jì)與敘州網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類型包括:做網(wǎng)站、成都網(wǎng)站設(shè)計(jì)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、域名注冊(cè)、網(wǎng)頁(yè)空間、企業(yè)郵箱。業(yè)務(wù)覆蓋敘州地區(qū)。

本段源碼可以學(xué)習(xí)的地方:

1. 考慮到效率問題,可以通過(guò)上下文的機(jī)制,在屬性被訪問的時(shí)候臨時(shí)構(gòu)建;

2. 可以重寫一些魔術(shù)方法,比如 __new__ 方法,在調(diào)用 object.__new__(cls) 前后進(jìn)行屬性的一些小設(shè)置;

3. 在本庫(kù)中使用的重寫魔術(shù)方法,上下文這兩種基礎(chǔ)之上,我們可以想到函數(shù)裝飾器,類裝飾器,異常捕獲,以及兩種上下文的結(jié)構(gòu);

靈活運(yùn)用這些手法,可以讓我們?cè)诖a架構(gòu)上更上一層,能夠更加省時(shí)省力。

from weakref import ref # ref用在了構(gòu)造大字典元素元組的第一個(gè)位置即 (ref(Thread), 線程字典)
from contextlib import contextmanager # 上下文管理,用來(lái)確保__dict__屬性的存在
from threading import current_thread, RLock
__all__ = ["local"]

class _localimpl: # local()._local__impl = _localimpl() # local()實(shí)例的屬性_local__impl就是這個(gè)類的實(shí)例
  """一個(gè)管理線程字典的類"""
  __slots__ = 'key', 'dicts', 'localargs', 'locallock', '__weakref__' # _local__impl有這么多屬性

  def __init__(self):
    # 這個(gè)self.key是用在線程對(duì)象的字典中的key
    # self.key使用的一個(gè)字符串,這樣既能運(yùn)行的快,
    # 但是通過(guò)'_threading_local._localimpl.' + str(id(self)也能保證不會(huì)沖突別的屬性

    self.key = '_threading_local._localimpl.' + str(id(self))
    #
    self.dicts = {} # 大字典
    # 格式是: { id(線程1):(ref(Thread), 線程1自身的字典), id(線程2):(ref(Thread), 線程2自身的字典), ... }

  def get_dict(self): # 從大字典中拿(ref(Thread), 線程字典), 然后取線程字典
    thread = current_thread()
    return self.dicts[id(thread)][1]

  def create_dict(self): # 為當(dāng)前線程創(chuàng)建一個(gè)線程字典,就是(ref(Thread), 線程字典)[1],即元組的第二部分
    localdict = {}
    key = self.key # key使用'_threading_local._localimpl.' + str(id(self)
    thread = current_thread() # 當(dāng)前線程
    idt = id(thread) # 當(dāng)前線程的id
    def local_deleted(_, key=key): # 這個(gè)函數(shù)不看 pass
      # When the localimpl is deleted, remove the thread attribute.
      thread = wrthread()
      if thread is not None:
        del thread.__dict__[key]
    def thread_deleted(_, idt=idt): # 這個(gè)函數(shù)不看 pass
      # When the thread is deleted, remove the local dict.
      # Note that this is suboptimal if the thread object gets
      # caught in a reference loop. We would like to be called
      # as soon as the OS-level thread ends instead.
      local = wrlocal()
      if local is not None:
        dct = local.dicts.pop(idt)
    wrlocal = ref(self, local_deleted)
    wrthread = ref(thread, thread_deleted) # 大字典中每一個(gè)線程對(duì)應(yīng)的元素的第一個(gè)位置: (ref(Thread), 小字典)
    thread.__dict__[key] = wrlocal
    self.dicts[idt] = wrthread, localdict # 在大字典中構(gòu)造: id(thread) : (ref(Thread), 小字典)
    return localdict


@contextmanager
def _patch(self):
  impl = object.__getattribute__(self, '_local__impl') # 此時(shí)的self是local(), 拿local()._local__impl
  try:
    dct = impl.get_dict()  # 然后從拿到的local()._local__impl調(diào)用線程字典管理類的local()._local__impl.get_dict()方法
                # 從20行到22這個(gè)get_dict()方法的定義可以看出來(lái),拿不到會(huì)報(bào)KeyError的

  except KeyError: # 如果拿不到報(bào) KeyError之后捕捉
    dct = impl.create_dict() # 然后再通過(guò)線程字典管理類臨時(shí)創(chuàng)建一個(gè)
    args, kw = impl.localargs # 這個(gè)時(shí)候把拿到
    self.__init__(*args, **kw)
  with impl.locallock: # 通過(guò)上下文的方式上鎖
    object.__setattr__(self, '__dict__', dct) # 給local() 實(shí)例增加__dict__屬性,這個(gè)屬性指向大字典中value元組的第二個(gè)元素,即線程小字典
    yield # 到目前為止,local()類的兩個(gè)屬性都構(gòu)造完成


class local: # local類
  __slots__ = '_local__impl', '__dict__' # local類有兩個(gè)屬性可以訪問

  def __new__(cls, *args, **kw):
    if (args or kw) and (cls.__init__ is object.__init__): # pass不看
      raise TypeError("Initialization arguments are not supported")
    self = object.__new__(cls) # pass不看
    impl = _localimpl() # _local_impl屬性對(duì)應(yīng)的是_localimpl類的實(shí)例
    impl.localargs = (args, kw) # _local_impl屬性即_localimpl類的實(shí)例 的 localargs屬性是一個(gè)元組
    impl.locallock = RLock() # pass 不看
    object.__setattr__(self, '_local__impl', impl)
    # 把_local__impl 增加給local(), 所以:local()._local__impl is ipml 即 _localimp()

    # __slots__規(guī)定了local()有兩個(gè)屬性,這里已經(jīng)設(shè)置了一個(gè)_local__impl;
    # 第二個(gè)屬性__dict__當(dāng)我們以后在訪問的時(shí)候使用上下文進(jìn)行臨時(shí)增加,比如第85行

    impl.create_dict() # 就是local._local__impl.create_dict()
    return self # 返回這個(gè)配置好_local__impl屬性的local()實(shí)例

  def __getattribute__(self, name): # 當(dāng)我們?nèi)ocal()的屬性時(shí)
    with _patch(self): # 會(huì)通過(guò)上下文先把數(shù)據(jù)準(zhǔn)備好
      return object.__getattribute__(self, name) # 在準(zhǔn)備好的數(shù)據(jù)中去拿要拿的屬性name

  def __setattr__(self, name, value):
    if name == '__dict__': # 這個(gè)判斷語(yǔ)句是控制local()實(shí)例的__dict__屬性只能讀不能被替換
      raise AttributeError(
        "%r object attribute '__dict__' is read-only"
        % self.__class__.__name__)
    with _patch(self): # 同理, 通過(guò)上下文先把__dict__構(gòu)造好
      return object.__setattr__(self, name, value) # 然后調(diào)用基類的方法設(shè)置屬性

  def __delattr__(self, name): # 刪除屬性,同理,和__setattr__手法相似
    if name == '__dict__':  # 這個(gè)判斷語(yǔ)句是控制local()實(shí)例的__dict__屬性只能讀不能被替換
      raise AttributeError(
        "%r object attribute '__dict__' is read-only"
        % self.__class__.__name__)
    with _patch(self): # 同理, 通過(guò)上下文先把__dict__構(gòu)造好
      return object.__delattr__(self, name)

# 整體架構(gòu)圖:
'''

                                        / —— key 屬性
                                       / —— dicts 屬性, 格式{id(Thread):(ref(Thread), 線程小字典)}
            ———— : _local__impl屬性  ---------- 是_local類的實(shí)例                           |
           /                             —— 其他屬性...                  |
           /             /—————————————————————————————————————————————————————————————————————————————————/
  創(chuàng)建一個(gè)local實(shí)例              /
           \            /
           \           /
            ———— : __dict__屬性 -------- 對(duì)應(yīng)的是_local__impl屬性的dicts 中的線程小字典



'''

以上是“python語(yǔ)言線程標(biāo)準(zhǔn)庫(kù)threading.local有什么用”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!

新聞標(biāo)題:python語(yǔ)言線程標(biāo)準(zhǔn)庫(kù)threading.local有什么用-創(chuàng)新互聯(lián)
網(wǎng)頁(yè)URL:http://bm7419.com/article14/gjsde.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制網(wǎng)站、網(wǎng)站設(shè)計(jì)、商城網(wǎng)站、關(guān)鍵詞優(yōu)化小程序開發(fā)、外貿(mào)建站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站建設(shè)