https://github.com/python/cpython/commit/b97328ef5d2435c08de3e4e2054c226f15b52d0f
commit: b97328ef5d2435c08de3e4e2054c226f15b52d0f
branch: main
author: Lysandros Nikolaou <lisandros...@gmail.com>
committer: hugovk <1324225+hug...@users.noreply.github.com>
date: 2025-05-05T15:00:15+03:00
summary:

gh-107006: Move `threading.local` docstring to docs (#131840)

Co-authored-by: Hugo van Kemenade <1324225+hug...@users.noreply.github.com>

files:
A Misc/NEWS.d/next/Documentation/2025-03-28-18-25-43.gh-issue-107006.BxFijD.rst
M Doc/library/threading.rst
M Lib/_threading_local.py

diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst
index d948493c2103df..de9ee427bd7fa6 100644
--- a/Doc/library/threading.rst
+++ b/Doc/library/threading.rst
@@ -260,23 +260,132 @@ All of the methods described below are executed 
atomically.
 Thread-Local Data
 -----------------
 
-Thread-local data is data whose values are thread specific.  To manage
-thread-local data, just create an instance of :class:`local` (or a
-subclass) and store attributes on it::
+Thread-local data is data whose values are thread specific. If you
+have data that you want to be local to a thread, create a
+:class:`local` object and use its attributes::
 
-  mydata = threading.local()
-  mydata.x = 1
+   >>> mydata = local()
+   >>> mydata.number = 42
+   >>> mydata.number
+   42
 
-The instance's values will be different for separate threads.
+You can also access the :class:`local`-object's dictionary::
+
+   >>> mydata.__dict__
+   {'number': 42}
+   >>> mydata.__dict__.setdefault('widgets', [])
+   []
+   >>> mydata.widgets
+   []
+
+If we access the data in a different thread::
+
+   >>> log = []
+   >>> def f():
+   ...     items = sorted(mydata.__dict__.items())
+   ...     log.append(items)
+   ...     mydata.number = 11
+   ...     log.append(mydata.number)
+
+   >>> import threading
+   >>> thread = threading.Thread(target=f)
+   >>> thread.start()
+   >>> thread.join()
+   >>> log
+   [[], 11]
+
+we get different data.  Furthermore, changes made in the other thread
+don't affect data seen in this thread::
+
+   >>> mydata.number
+   42
+
+Of course, values you get from a :class:`local` object, including their
+:attr:`~object.__dict__` attribute, are for whatever thread was current
+at the time the attribute was read.  For that reason, you generally
+don't want to save these values across threads, as they apply only to
+the thread they came from.
+
+You can create custom :class:`local` objects by subclassing the
+:class:`local` class::
+
+   >>> class MyLocal(local):
+   ...     number = 2
+   ...     def __init__(self, /, **kw):
+   ...         self.__dict__.update(kw)
+   ...     def squared(self):
+   ...         return self.number ** 2
+
+This can be useful to support default values, methods and
+initialization.  Note that if you define an :py:meth:`~object.__init__`
+method, it will be called each time the :class:`local` object is used
+in a separate thread.  This is necessary to initialize each thread's
+dictionary.
+
+Now if we create a :class:`local` object::
+
+   >>> mydata = MyLocal(color='red')
+
+we have a default number::
+
+   >>> mydata.number
+   2
+
+an initial color::
+
+   >>> mydata.color
+   'red'
+   >>> del mydata.color
+
+And a method that operates on the data::
+
+   >>> mydata.squared()
+   4
+
+As before, we can access the data in a separate thread::
+
+   >>> log = []
+   >>> thread = threading.Thread(target=f)
+   >>> thread.start()
+   >>> thread.join()
+   >>> log
+   [[('color', 'red')], 11]
+
+without affecting this thread's data::
+
+   >>> mydata.number
+   2
+   >>> mydata.color
+   Traceback (most recent call last):
+   ...
+   AttributeError: 'MyLocal' object has no attribute 'color'
+
+Note that subclasses can define :term:`__slots__`, but they are not
+thread local. They are shared across threads::
+
+   >>> class MyLocal(local):
+   ...     __slots__ = 'number'
+
+   >>> mydata = MyLocal()
+   >>> mydata.number = 42
+   >>> mydata.color = 'red'
+
+So, the separate thread::
+
+   >>> thread = threading.Thread(target=f)
+   >>> thread.start()
+   >>> thread.join()
+
+affects what we see::
+
+   >>> mydata.number
+   11
 
 
 .. class:: local()
 
    A class that represents thread-local data.
 
-   For more details and extensive examples, see the documentation string of the
-   :mod:`!_threading_local` module: :source:`Lib/_threading_local.py`.
-
 
 .. _thread-objects:
 
diff --git a/Lib/_threading_local.py b/Lib/_threading_local.py
index b006d76c4e23df..0b9e5d3bbf6ef6 100644
--- a/Lib/_threading_local.py
+++ b/Lib/_threading_local.py
@@ -4,128 +4,6 @@
  class.  Depending on the version of Python you're using, there may be a
  faster one available.  You should always import the `local` class from
  `threading`.)
-
-Thread-local objects support the management of thread-local data.
-If you have data that you want to be local to a thread, simply create
-a thread-local object and use its attributes:
-
-  >>> mydata = local()
-  >>> mydata.number = 42
-  >>> mydata.number
-  42
-
-You can also access the local-object's dictionary:
-
-  >>> mydata.__dict__
-  {'number': 42}
-  >>> mydata.__dict__.setdefault('widgets', [])
-  []
-  >>> mydata.widgets
-  []
-
-What's important about thread-local objects is that their data are
-local to a thread. If we access the data in a different thread:
-
-  >>> log = []
-  >>> def f():
-  ...     items = sorted(mydata.__dict__.items())
-  ...     log.append(items)
-  ...     mydata.number = 11
-  ...     log.append(mydata.number)
-
-  >>> import threading
-  >>> thread = threading.Thread(target=f)
-  >>> thread.start()
-  >>> thread.join()
-  >>> log
-  [[], 11]
-
-we get different data.  Furthermore, changes made in the other thread
-don't affect data seen in this thread:
-
-  >>> mydata.number
-  42
-
-Of course, values you get from a local object, including a __dict__
-attribute, are for whatever thread was current at the time the
-attribute was read.  For that reason, you generally don't want to save
-these values across threads, as they apply only to the thread they
-came from.
-
-You can create custom local objects by subclassing the local class:
-
-  >>> class MyLocal(local):
-  ...     number = 2
-  ...     def __init__(self, /, **kw):
-  ...         self.__dict__.update(kw)
-  ...     def squared(self):
-  ...         return self.number ** 2
-
-This can be useful to support default values, methods and
-initialization.  Note that if you define an __init__ method, it will be
-called each time the local object is used in a separate thread.  This
-is necessary to initialize each thread's dictionary.
-
-Now if we create a local object:
-
-  >>> mydata = MyLocal(color='red')
-
-Now we have a default number:
-
-  >>> mydata.number
-  2
-
-an initial color:
-
-  >>> mydata.color
-  'red'
-  >>> del mydata.color
-
-And a method that operates on the data:
-
-  >>> mydata.squared()
-  4
-
-As before, we can access the data in a separate thread:
-
-  >>> log = []
-  >>> thread = threading.Thread(target=f)
-  >>> thread.start()
-  >>> thread.join()
-  >>> log
-  [[('color', 'red')], 11]
-
-without affecting this thread's data:
-
-  >>> mydata.number
-  2
-  >>> mydata.color
-  Traceback (most recent call last):
-  ...
-  AttributeError: 'MyLocal' object has no attribute 'color'
-
-Note that subclasses can define slots, but they are not thread
-local. They are shared across threads:
-
-  >>> class MyLocal(local):
-  ...     __slots__ = 'number'
-
-  >>> mydata = MyLocal()
-  >>> mydata.number = 42
-  >>> mydata.color = 'red'
-
-So, the separate thread:
-
-  >>> thread = threading.Thread(target=f)
-  >>> thread.start()
-  >>> thread.join()
-
-affects what we see:
-
-  >>> mydata.number
-  11
-
->>> del mydata
 """
 
 from weakref import ref
diff --git 
a/Misc/NEWS.d/next/Documentation/2025-03-28-18-25-43.gh-issue-107006.BxFijD.rst 
b/Misc/NEWS.d/next/Documentation/2025-03-28-18-25-43.gh-issue-107006.BxFijD.rst
new file mode 100644
index 00000000000000..eb55c2437f917f
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Documentation/2025-03-28-18-25-43.gh-issue-107006.BxFijD.rst
@@ -0,0 +1,2 @@
+Move documentation and example code for :class:`threading.local` from its
+docstring to the official docs.

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com

Reply via email to