SoFunction
Updated on 2024-11-19

Interpretation of the python language threading standard library summary

This source code can be learned from this paragraph:

1. Considering efficiency, this can be constructed on an ad hoc basis when the attribute is accessed through the mechanism of a context;

2. It is possible to rewrite some of the magic methods, such as __new__ method in the call to theobject.__new__(cls) Some minor settings of properties before and after;

3. On top of the two foundations of rewrite magic methods and contexts used in this library, we can think of function decorators, class decorators, exception catching, and two contextual structures;

Flexibility in the use of these techniques will allow us to go to the next level of code architecture and be able to save more time and effort.

from weakref import ref # ref is used in the first position of constructing a tuple of large dictionary elements i.e. (ref(Thread), thread dictionary)
from contextlib import contextmanager # Context management, used to ensure the existence of the __dict__ attribute
from threading import current_thread, RLock
__all__ = ["local"]

class _localimpl: # local(). _local__impl = _localimpl() # The attribute _local__impl of a local() instance is the instance of the class
  """A class that manages a dictionary of threads."""
  __slots__ = 'key', 'dicts', 'localargs', 'locallock', '__weakref__' # __local__impl has so many attributes

  def __init__(self):
    # It's using the key from the thread object's dictionary #
    # A string to use so that it runs both fast and
    # But it's also possible to ensure that other attributes don't conflict by using '_threading_local._localimpl.' + str(id(self))

     = '_threading_local._localimpl.' + str(id(self))
    #
     = {} # The Big Dictionary
    # The format is: { id(Thread1): (ref(Thread), Thread1's own dictionary), id(Thread2): (ref(Thread), Thread2's own dictionary), ... }

  def get_dict(self): # Take (ref(Thread), thread dictionary) from the big dictionary, then take the thread dictionary
    thread = current_thread()
    return [id(thread)][1]

  def create_dict(self): # Create a thread dictionary for the current thread, which is (ref(Thread), thread dictionary)[1], the second part of the tuple
    localdict = {}
    key =  # keyutilization'_threading_local._localimpl.' + str(id(self)
    thread = current_thread() # Current thread
    idt = id(thread) # id of the current thread
    def local_deleted(_, key=key): # This function doesn't look 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): # This function doesn't look 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 = (idt)
    wrlocal = ref(self, local_deleted)
    wrthread = ref(thread, thread_deleted) # First position of the element corresponding to each thread in the big dictionary: (ref(Thread), small dictionary)
    thread.__dict__[key] = wrlocal
    [idt] = wrthread, localdict # Construct in large dictionary: id(thread) : (ref(Thread), small dictionary)
    return localdict


@contextmanager
def _patch(self):
  impl = object.__getattribute__(self, '_local__impl') # This time self is local(), take local(). _local__impl
  try:
    dct = impl.get_dict()  # Then call the threaded dictionary manager class's local(). __local__impl calls the threaded dictionary management class's local(). __local__impl.get_dict() method
                # As you can see from the definition of the get_dict() method on lines 20 through 22, failure to get it will result in a KeyError.

  except KeyError: # If you can't get it, report a KeyError and then capture the
    dct = impl.create_dict() # And then temporarily create a threaded dictionary via the threaded dictionary manager class #
    args, kw =  # This is the time to get
    self.__init__(*args, **kw)
  with : # Locking by context
    object.__setattr__(self, '__dict__', dct) # Add the __dict__ attribute to the local() instance, which points to the second element of the value tuple in the big dictionary, the threaded little dictionary
    yield # So far, both properties of the local() class have been constructed.


class local: # local class
  __slots__ = '_local__impl', '__dict__' # The local class has two properties that can be accessed

  def __new__(cls, *args, **kw):
    if (args or kw) and (cls.__init__ is object.__init__): # Pass without looking
      raise TypeError("Initialization arguments are not supported")
    self = object.__new__(cls) # Pass without looking
    impl = _localimpl() # The _local_impl attribute corresponds to an instance of the _localimpl class
     = (args, kw) # The localargs attribute of the _local_impl attribute, which is an instance of the _localimpl class, is a tuple.
     = RLock() # pass Don't look
    object.__setattr__(self, '_local__impl', impl)
    # Add _local__impl to local(), so: local(). _local__impl is ipml i.e. _localimp()

    # __slots__ specifies that local() has two attributes, and a _local__impl has been set here;
    # The second attribute __dict__ is added temporarily when we access it later using the context, e.g. line 85

    impl.create_dict() # is local.__local__impl.create_dict()
    return self # Return this instance of local() with the _local__impl attribute configured

  def __getattribute__(self, name): # When we take the attribute of local()
    with _patch(self): # It'll get the data ready first by contextualizing it #
      return object.__getattribute__(self, name) # Go get the attribute name in the prepared data.

  def __setattr__(self, name, value):
    if name == '__dict__': # This judgment statement controls that the __dict__ attribute of a local() instance can only be read and cannot be replaced.
      raise AttributeError(
        "%r object attribute '__dict__' is read-only"
        % self.__class__.__name__)
    with _patch(self): # Similarly, __dict__ is constructed by context first #
      return object.__setattr__(self, name, value) # Then call the base class method to set the property

  def __delattr__(self, name): # Remove attributes, similar to __setattr__.
    if name == '__dict__':  # This judgment statement controls that the __dict__ attribute of a local() instance can only be read and cannot be replaced.
      raise AttributeError(
        "%r object attribute '__dict__' is read-only"
        % self.__class__.__name__)
    with _patch(self): # Similarly, __dict__ is constructed by context first #
      return object.__delattr__(self, name)

# Overall architecture diagram:
'''

                                        / -- key attribute
                                       / -- dicts attribute, format {id(Thread):(ref(Thread), thread small dictionary)}
            ---- : _local__impl attribute ---------- is an instance of the _local class |
           / -- Other properties...                  |
           / /--------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- --/
  Create a local instance /
           \ /
           \ /
            ---- : The __dict__ attribute -------- corresponds to the small dictionary of threads in the dicts of the __local__impl attribute



'''

This is the entire knowledge content of this presentation, thank you for learning and supporting me.