Kaydet (Commit) ef4d2867 authored tarafından R David Murray's avatar R David Murray

#10968: commit threading doc changes and corresponding whatsnew entry.

It is unfortunate that the '_' names were not kept as aliases, and that RLock
was not also converted to a class, but it is now too late to change either of
those things for 3.3.
üst fc9adb62
...@@ -916,7 +916,7 @@ object -- see :ref:`multiprocessing-managers`. ...@@ -916,7 +916,7 @@ object -- see :ref:`multiprocessing-managers`.
.. class:: Condition([lock]) .. class:: Condition([lock])
A condition variable: a clone of :class:`threading.Condition`. A condition variable: an alias for :class:`threading.Condition`.
If *lock* is specified then it should be a :class:`Lock` or :class:`RLock` If *lock* is specified then it should be a :class:`Lock` or :class:`RLock`
object from :mod:`multiprocessing`. object from :mod:`multiprocessing`.
......
...@@ -21,7 +21,7 @@ The :mod:`dummy_threading` module is provided for situations where ...@@ -21,7 +21,7 @@ The :mod:`dummy_threading` module is provided for situations where
supported by this module. supported by this module.
This module defines the following functions and objects: This module defines the following functions:
.. function:: active_count() .. function:: active_count()
...@@ -30,16 +30,6 @@ This module defines the following functions and objects: ...@@ -30,16 +30,6 @@ This module defines the following functions and objects:
count is equal to the length of the list returned by :func:`.enumerate`. count is equal to the length of the list returned by :func:`.enumerate`.
.. function:: Condition()
:noindex:
A factory function that returns a new condition variable object. A condition
variable allows one or more threads to wait until they are notified by another
thread.
See :ref:`condition-objects`.
.. function:: current_thread() .. function:: current_thread()
Return the current :class:`Thread` object, corresponding to the caller's thread Return the current :class:`Thread` object, corresponding to the caller's thread
...@@ -67,88 +57,6 @@ This module defines the following functions and objects: ...@@ -67,88 +57,6 @@ This module defines the following functions and objects:
and threads that have not yet been started. and threads that have not yet been started.
.. function:: Event()
:noindex:
A factory function that returns a new event object. An event manages a flag
that can be set to true with the :meth:`~Event.set` method and reset to false
with the :meth:`clear` method. The :meth:`wait` method blocks until the flag
is true.
See :ref:`event-objects`.
.. class:: local
A class that represents thread-local data. Thread-local data are 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::
mydata = threading.local()
mydata.x = 1
The instance's values will be different for separate threads.
For more details and extensive examples, see the documentation string of the
:mod:`_threading_local` module.
.. function:: Lock()
A factory function that returns a new primitive lock object. Once a thread has
acquired it, subsequent attempts to acquire it block, until it is released; any
thread may release it.
See :ref:`lock-objects`.
.. function:: RLock()
A factory function that returns a new reentrant lock object. A reentrant lock
must be released by the thread that acquired it. Once a thread has acquired a
reentrant lock, the same thread may acquire it again without blocking; the
thread must release it once for each time it has acquired it.
See :ref:`rlock-objects`.
.. function:: Semaphore(value=1)
:noindex:
A factory function that returns a new semaphore object. A semaphore manages a
counter representing the number of :meth:`release` calls minus the number of
:meth:`acquire` calls, plus an initial value. The :meth:`acquire` method blocks
if necessary until it can return without making the counter negative. If not
given, *value* defaults to 1.
See :ref:`semaphore-objects`.
.. function:: BoundedSemaphore(value=1)
A factory function that returns a new bounded semaphore object. A bounded
semaphore checks to make sure its current value doesn't exceed its initial
value. If it does, :exc:`ValueError` is raised. In most situations semaphores
are used to guard resources with limited capacity. If the semaphore is released
too many times it's a sign of a bug. If not given, *value* defaults to 1.
.. class:: Thread
A class that represents a thread of control. This class can be safely
subclassed in a limited fashion.
See :ref:`thread-objects`.
.. class:: Timer
:noindex:
A thread that executes a function after a specified interval has passed.
See :ref:`timer-objects`.
.. function:: settrace(func) .. function:: settrace(func)
.. index:: single: trace function .. index:: single: trace function
...@@ -197,7 +105,8 @@ This module also defines the following constant: ...@@ -197,7 +105,8 @@ This module also defines the following constant:
.. versionadded:: 3.2 .. versionadded:: 3.2
Detailed interfaces for the objects are documented below. This module defines a number of classes, which are detailed in the sections
below.
The design of this module is loosely based on Java's threading model. However, The design of this module is loosely based on Java's threading model. However,
where Java makes locks and condition variables basic behavior of every object, where Java makes locks and condition variables basic behavior of every object,
...@@ -210,17 +119,38 @@ when implemented, are mapped to module-level functions. ...@@ -210,17 +119,38 @@ when implemented, are mapped to module-level functions.
All of the methods described below are executed atomically. 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::
mydata = threading.local()
mydata.x = 1
The instance's values will be different for separate threads.
.. 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.
.. _thread-objects: .. _thread-objects:
Thread Objects Thread Objects
-------------- --------------
This class represents an activity that is run in a separate thread of control. The :class:`Thread` class represents an activity that is run in a separate
There are two ways to specify the activity: by passing a callable object to the thread of control. There are two ways to specify the activity: by passing a
constructor, or by overriding the :meth:`~Thread.run` method in a subclass. callable object to the constructor, or by overriding the :meth:`~Thread.run`
No other methods (except for the constructor) should be overridden in a method in a subclass. No other methods (except for the constructor) should be
subclass. In other words, *only* override the :meth:`~Thread.__init__` overridden in a subclass. In other words, *only* override the
and :meth:`~Thread.run` methods of this class. :meth:`~Thread.__init__` and :meth:`~Thread.run` methods of this class.
Once a thread object is created, its activity must be started by calling the Once a thread object is created, its activity must be started by calling the
thread's :meth:`~Thread.start` method. This invokes the :meth:`~Thread.run` thread's :meth:`~Thread.start` method. This invokes the :meth:`~Thread.run`
...@@ -419,45 +349,55 @@ is not defined, and may vary across implementations. ...@@ -419,45 +349,55 @@ is not defined, and may vary across implementations.
All methods are executed atomically. All methods are executed atomically.
.. method:: Lock.acquire(blocking=True, timeout=-1) .. class:: Lock()
Acquire a lock, blocking or non-blocking. The class implementing primitive lock objects. Once a thread has acquired a
lock, subsequent attempts to acquire it block, until it is released; any
thread may release it.
When invoked with the *blocking* argument set to ``True`` (the default), .. versionchanged:: 3.3
block until the lock is unlocked, then set it to locked and return ``True``. Changed from a factory function to a class.
When invoked with the *blocking* argument set to ``False``, do not block.
If a call with *blocking* set to ``True`` would block, return ``False``
immediately; otherwise, set the lock to locked and return ``True``.
When invoked with the floating-point *timeout* argument set to a positive .. method:: acquire(blocking=True, timeout=-1)
value, block for at most the number of seconds specified by *timeout*
and as long as the lock cannot be acquired. A negative *timeout* argument
specifies an unbounded wait. It is forbidden to specify a *timeout*
when *blocking* is false.
The return value is ``True`` if the lock is acquired successfully, Acquire a lock, blocking or non-blocking.
``False`` if not (for example if the *timeout* expired).
.. versionchanged:: 3.2 When invoked with the *blocking* argument set to ``True`` (the default),
The *timeout* parameter is new. block until the lock is unlocked, then set it to locked and return ``True``.
.. versionchanged:: 3.2 When invoked with the *blocking* argument set to ``False``, do not block.
Lock acquires can now be interrupted by signals on POSIX. If a call with *blocking* set to ``True`` would block, return ``False``
immediately; otherwise, set the lock to locked and return ``True``.
When invoked with the floating-point *timeout* argument set to a positive
value, block for at most the number of seconds specified by *timeout*
and as long as the lock cannot be acquired. A negative *timeout* argument
specifies an unbounded wait. It is forbidden to specify a *timeout*
when *blocking* is false.
.. method:: Lock.release() The return value is ``True`` if the lock is acquired successfully,
``False`` if not (for example if the *timeout* expired).
Release a lock. This can be called from any thread, not only the thread .. versionchanged:: 3.2
which has acquired the lock. The *timeout* parameter is new.
When the lock is locked, reset it to unlocked, and return. If any other threads .. versionchanged:: 3.2
are blocked waiting for the lock to become unlocked, allow exactly one of them Lock acquires can now be interrupted by signals on POSIX.
to proceed.
.. method:: release()
Release a lock. This can be called from any thread, not only the thread
which has acquired the lock.
When the lock is locked, reset it to unlocked, and return. If any other threads
are blocked waiting for the lock to become unlocked, allow exactly one of them
to proceed.
When invoked on an unlocked lock, a :exc:`RuntimeError` is raised. When invoked on an unlocked lock, a :exc:`RuntimeError` is raised.
There is no return value. There is no return value.
.. _rlock-objects: .. _rlock-objects:
...@@ -481,47 +421,59 @@ allows another thread blocked in :meth:`~Lock.acquire` to proceed. ...@@ -481,47 +421,59 @@ allows another thread blocked in :meth:`~Lock.acquire` to proceed.
Reentrant locks also support the :ref:`context manager protocol <with-locks>`. Reentrant locks also support the :ref:`context manager protocol <with-locks>`.
.. method:: RLock.acquire(blocking=True, timeout=-1) .. class:: RLock()
Acquire a lock, blocking or non-blocking. This class implements reentrant lock objects. A reentrant lock must be
released by the thread that acquired it. Once a thread has acquired a
reentrant lock, the same thread may acquire it again without blocking; the
thread must release it once for each time it has acquired it.
When invoked without arguments: if this thread already owns the lock, increment Note that ``RLock`` is actually a factory function which returns an instance
the recursion level by one, and return immediately. Otherwise, if another of the most efficient version of the concrete RLock class that is supported
thread owns the lock, block until the lock is unlocked. Once the lock is by the platform.
unlocked (not owned by any thread), then grab ownership, set the recursion level
to one, and return. If more than one thread is blocked waiting until the lock
is unlocked, only one at a time will be able to grab ownership of the lock.
There is no return value in this case.
When invoked with the *blocking* argument set to true, do the same thing as when
called without arguments, and return true.
When invoked with the *blocking* argument set to false, do not block. If a call .. method:: acquire(blocking=True, timeout=-1)
without an argument would block, return false immediately; otherwise, do the
same thing as when called without arguments, and return true.
When invoked with the floating-point *timeout* argument set to a positive Acquire a lock, blocking or non-blocking.
value, block for at most the number of seconds specified by *timeout*
and as long as the lock cannot be acquired. Return true if the lock has
been acquired, false if the timeout has elapsed.
.. versionchanged:: 3.2 When invoked without arguments: if this thread already owns the lock, increment
The *timeout* parameter is new. the recursion level by one, and return immediately. Otherwise, if another
thread owns the lock, block until the lock is unlocked. Once the lock is
unlocked (not owned by any thread), then grab ownership, set the recursion level
to one, and return. If more than one thread is blocked waiting until the lock
is unlocked, only one at a time will be able to grab ownership of the lock.
There is no return value in this case.
When invoked with the *blocking* argument set to true, do the same thing as when
called without arguments, and return true.
.. method:: RLock.release() When invoked with the *blocking* argument set to false, do not block. If a call
without an argument would block, return false immediately; otherwise, do the
same thing as when called without arguments, and return true.
Release a lock, decrementing the recursion level. If after the decrement it is When invoked with the floating-point *timeout* argument set to a positive
zero, reset the lock to unlocked (not owned by any thread), and if any other value, block for at most the number of seconds specified by *timeout*
threads are blocked waiting for the lock to become unlocked, allow exactly one and as long as the lock cannot be acquired. Return true if the lock has
of them to proceed. If after the decrement the recursion level is still been acquired, false if the timeout has elapsed.
nonzero, the lock remains locked and owned by the calling thread.
Only call this method when the calling thread owns the lock. A .. versionchanged:: 3.2
:exc:`RuntimeError` is raised if this method is called when the lock is The *timeout* parameter is new.
unlocked.
There is no return value.
.. method:: release()
Release a lock, decrementing the recursion level. If after the decrement it is
zero, reset the lock to unlocked (not owned by any thread), and if any other
threads are blocked waiting for the lock to become unlocked, allow exactly one
of them to proceed. If after the decrement the recursion level is still
nonzero, the lock remains locked and owned by the calling thread.
Only call this method when the calling thread owns the lock. A
:exc:`RuntimeError` is raised if this method is called when the lock is
unlocked.
There is no return value.
.. _condition-objects: .. _condition-objects:
...@@ -556,10 +508,6 @@ not return from their :meth:`~Condition.wait` call immediately, but only when ...@@ -556,10 +508,6 @@ not return from their :meth:`~Condition.wait` call immediately, but only when
the thread that called :meth:`~Condition.notify` or :meth:`~Condition.notify_all` the thread that called :meth:`~Condition.notify` or :meth:`~Condition.notify_all`
finally relinquishes ownership of the lock. finally relinquishes ownership of the lock.
Usage
^^^^^
The typical programming style using condition variables uses the lock to The typical programming style using condition variables uses the lock to
synchronize access to some shared state; threads that are interested in a synchronize access to some shared state; threads that are interested in a
particular change of state call :meth:`~Condition.wait` repeatedly until they particular change of state call :meth:`~Condition.wait` repeatedly until they
...@@ -598,15 +546,18 @@ waiting threads. E.g. in a typical producer-consumer situation, adding one ...@@ -598,15 +546,18 @@ waiting threads. E.g. in a typical producer-consumer situation, adding one
item to the buffer only needs to wake up one consumer thread. item to the buffer only needs to wake up one consumer thread.
Interface
^^^^^^^^^
.. class:: Condition(lock=None) .. class:: Condition(lock=None)
This class implements condition variable objects. A condition variable
allows one or more threads to wait until they are notified by another thread.
If the *lock* argument is given and not ``None``, it must be a :class:`Lock` If the *lock* argument is given and not ``None``, it must be a :class:`Lock`
or :class:`RLock` object, and it is used as the underlying lock. Otherwise, or :class:`RLock` object, and it is used as the underlying lock. Otherwise,
a new :class:`RLock` object is created and used as the underlying lock. a new :class:`RLock` object is created and used as the underlying lock.
.. versionchanged:: 3.3
changed from a factory function to a class.
.. method:: acquire(*args) .. method:: acquire(*args)
Acquire the underlying lock. This method calls the corresponding method on Acquire the underlying lock. This method calls the corresponding method on
...@@ -716,10 +667,19 @@ Semaphores also support the :ref:`context manager protocol <with-locks>`. ...@@ -716,10 +667,19 @@ Semaphores also support the :ref:`context manager protocol <with-locks>`.
.. class:: Semaphore(value=1) .. class:: Semaphore(value=1)
This class implements semaphore objects. A semaphore manages a counter
representing the number of :meth:`release` calls minus the number of
:meth:`acquire` calls, plus an initial value. The :meth:`acquire` method
blocks if necessary until it can return without making the counter negative.
If not given, *value* defaults to 1.
The optional argument gives the initial *value* for the internal counter; it The optional argument gives the initial *value* for the internal counter; it
defaults to ``1``. If the *value* given is less than 0, :exc:`ValueError` is defaults to ``1``. If the *value* given is less than 0, :exc:`ValueError` is
raised. raised.
.. versionchanged:: 3.3
changed from a factory function to a class.
.. method:: acquire(blocking=True, timeout=None) .. method:: acquire(blocking=True, timeout=None)
Acquire a semaphore. Acquire a semaphore.
...@@ -752,6 +712,18 @@ Semaphores also support the :ref:`context manager protocol <with-locks>`. ...@@ -752,6 +712,18 @@ Semaphores also support the :ref:`context manager protocol <with-locks>`.
than zero again, wake up that thread. than zero again, wake up that thread.
.. class:: BoundedSemaphore(value=1)
Class implementing bounded semaphore objects. A bounded semaphore checks to
make sure its current value doesn't exceed its initial value. If it does,
:exc:`ValueError` is raised. In most situations semaphores are used to guard
resources with limited capacity. If the semaphore is released too many times
it's a sign of a bug. If not given, *value* defaults to 1.
.. versionchanged:: 3.3
changed from a factory function to a class.
.. _semaphore-examples: .. _semaphore-examples:
:class:`Semaphore` Example :class:`Semaphore` Example
...@@ -763,7 +735,7 @@ you should use a bounded semaphore. Before spawning any worker threads, your ...@@ -763,7 +735,7 @@ you should use a bounded semaphore. Before spawning any worker threads, your
main thread would initialize the semaphore:: main thread would initialize the semaphore::
maxconnections = 5 maxconnections = 5
... # ...
pool_sema = BoundedSemaphore(value=maxconnections) pool_sema = BoundedSemaphore(value=maxconnections)
Once spawned, worker threads call the semaphore's acquire and release methods Once spawned, worker threads call the semaphore's acquire and release methods
...@@ -772,7 +744,7 @@ when they need to connect to the server:: ...@@ -772,7 +744,7 @@ when they need to connect to the server::
with pool_sema: with pool_sema:
conn = connectdb() conn = connectdb()
try: try:
... use connection ... # ... use connection ...
finally: finally:
conn.close() conn.close()
...@@ -795,7 +767,13 @@ method. The :meth:`~Event.wait` method blocks until the flag is true. ...@@ -795,7 +767,13 @@ method. The :meth:`~Event.wait` method blocks until the flag is true.
.. class:: Event() .. class:: Event()
The internal flag is initially false. Class implementing event objects. An event manages a flag that can be set to
true with the :meth:`~Event.set` method and reset to false with the
:meth:`clear` method. The :meth:`wait` method blocks until the flag is true.
The flag is initially false.
.. versionchanged:: 3.3
changed from a factory function to a class.
.. method:: is_set() .. method:: is_set()
...@@ -860,6 +838,9 @@ For example:: ...@@ -860,6 +838,9 @@ For example::
Create a timer that will run *function* with arguments *args* and keyword Create a timer that will run *function* with arguments *args* and keyword
arguments *kwargs*, after *interval* seconds have passed. arguments *kwargs*, after *interval* seconds have passed.
.. versionchanged:: 3.3
changed from a factory function to a class.
.. method:: cancel() .. method:: cancel()
Stop the timer, and cancel the execution of the timer's action. This will Stop the timer, and cancel the execution of the timer's action. This will
......
...@@ -1945,6 +1945,12 @@ of text (:issue:`13857`). ...@@ -1945,6 +1945,12 @@ of text (:issue:`13857`).
threading threading
--------- ---------
:class:`threading.Condition`, :class:`threading.Semaphore`,
:class:`threading.BoundedSempaphore`, :class:`threading.Event`, and
:class:`threading.Timer`, all of which used to be factory functions returning a
class instance, are now classes and may be subclassed. (Contributed by Éric
Araujo in :issue:`109681`).
The :class:`threading.Thread` constructor now accepts a ``daemon`` keyword The :class:`threading.Thread` constructor now accepts a ``daemon`` keyword
argument to override the default behavior of inheriting the ``deamon`` flag argument to override the default behavior of inheriting the ``deamon`` flag
value from the parent thread (:issue:`6064`). value from the parent thread (:issue:`6064`).
...@@ -2331,6 +2337,10 @@ Porting Python code ...@@ -2331,6 +2337,10 @@ Porting Python code
make decisions affected by the AST version, use :attr:`sys.version_info` make decisions affected by the AST version, use :attr:`sys.version_info`
to make the decision. to make the decision.
* Code that used to work around the fact that the :mod:`threading` module used
factory functions by subclassing the private classes will need to change to
subclass the now-public classes.
Porting C code Porting C code
-------------- --------------
......
...@@ -3031,11 +3031,11 @@ Library ...@@ -3031,11 +3031,11 @@ Library
- Issue #8887: "pydoc somebuiltin.somemethod" (or help('somebuiltin.somemethod') - Issue #8887: "pydoc somebuiltin.somemethod" (or help('somebuiltin.somemethod')
in Python code) now finds the doc of the method. in Python code) now finds the doc of the method.
- Issue #10968: Remove indirection in threading. The public names (Thread, - Issue #10968: Remove indirection in threading. The public names (Event,
Condition, etc.) used to be factory functions returning instances of hidden Condition, etc.) used to be factory functions returning instances of hidden
classes (_Thread, _Condition, etc.), because (if Guido recalls correctly) this classes (_Event, _Condition, etc.), because (if Guido recalls correctly) this
code pre-dates the ability to subclass extension types. It is now possible to code pre-dates the ability to subclass extension types. It is now possible
inherit from Thread and other classes, without having to import the private to inherit from these classes, without having to import the private
underscored names like multiprocessing did. underscored names like multiprocessing did.
- Issue #9723: Add shlex.quote functions, to escape filenames and command - Issue #9723: Add shlex.quote functions, to escape filenames and command
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment