summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLysandros Nikolaou <lisandrosnik@gmail.com>2025-05-05 12:00:15 (GMT)
committerGitHub <noreply@github.com>2025-05-05 12:00:15 (GMT)
commitb97328ef5d2435c08de3e4e2054c226f15b52d0f (patch)
tree8e9ce55b29c8da419bf0e6b6c27ff7d61c4b3306
parent8467026ed66ca3abefe3a13860d2633eae3d7164 (diff)
downloadcpython-b97328ef5d2435c08de3e4e2054c226f15b52d0f.zip
cpython-b97328ef5d2435c08de3e4e2054c226f15b52d0f.tar.gz
cpython-b97328ef5d2435c08de3e4e2054c226f15b52d0f.tar.bz2
gh-107006: Move `threading.local` docstring to docs (#131840)
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
-rw-r--r--Doc/library/threading.rst127
-rw-r--r--Lib/_threading_local.py122
-rw-r--r--Misc/NEWS.d/next/Documentation/2025-03-28-18-25-43.gh-issue-107006.BxFijD.rst2
3 files changed, 120 insertions, 131 deletions
diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst
index d948493..de9ee42 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 b006d76..0b9e5d3 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 0000000..eb55c24
--- /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.