mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
bpo-32253: Deprecate with statement and bare await for asyncio locks (GH-4764)
* Add test for 'with (yield from lock)' * Deprecate with statement for asyncio locks * Document the deprecation
This commit is contained in:
parent
a9f8df646a
commit
28d8d14013
5 changed files with 108 additions and 55 deletions
|
@ -23,11 +23,9 @@ module (:class:`~threading.Lock`, :class:`~threading.Event`,
|
|||
:class:`~threading.BoundedSemaphore`), but it has no *timeout* parameter. The
|
||||
:func:`asyncio.wait_for` function can be used to cancel a task after a timeout.
|
||||
|
||||
Locks
|
||||
-----
|
||||
|
||||
Lock
|
||||
^^^^
|
||||
----
|
||||
|
||||
.. class:: Lock(\*, loop=None)
|
||||
|
||||
|
@ -37,8 +35,9 @@ Lock
|
|||
particular coroutine when locked. A primitive lock is in one of two states,
|
||||
'locked' or 'unlocked'.
|
||||
|
||||
It is created in the unlocked state. It has two basic methods, :meth:`acquire`
|
||||
and :meth:`release`. When the state is unlocked, acquire() changes the state to
|
||||
The lock is created in the unlocked state.
|
||||
It has two basic methods, :meth:`acquire` and :meth:`release`.
|
||||
When the state is unlocked, acquire() changes the state to
|
||||
locked and returns immediately. When the state is locked, acquire() blocks
|
||||
until a call to release() in another coroutine changes it to unlocked, then
|
||||
the acquire() call resets it to locked and returns. The release() method
|
||||
|
@ -51,38 +50,12 @@ Lock
|
|||
resets the state to unlocked; first coroutine which is blocked in acquire()
|
||||
is being processed.
|
||||
|
||||
:meth:`acquire` is a coroutine and should be called with ``yield from``.
|
||||
:meth:`acquire` is a coroutine and should be called with ``await``.
|
||||
|
||||
Locks also support the context management protocol. ``(yield from lock)``
|
||||
should be used as the context manager expression.
|
||||
Locks support the :ref:`context management protocol <async-with-locks>`.
|
||||
|
||||
This class is :ref:`not thread safe <asyncio-multithreading>`.
|
||||
|
||||
Usage::
|
||||
|
||||
lock = Lock()
|
||||
...
|
||||
yield from lock
|
||||
try:
|
||||
...
|
||||
finally:
|
||||
lock.release()
|
||||
|
||||
Context manager usage::
|
||||
|
||||
lock = Lock()
|
||||
...
|
||||
with (yield from lock):
|
||||
...
|
||||
|
||||
Lock objects can be tested for locking state::
|
||||
|
||||
if not lock.locked():
|
||||
yield from lock
|
||||
else:
|
||||
# lock is acquired
|
||||
...
|
||||
|
||||
.. method:: locked()
|
||||
|
||||
Return ``True`` if the lock is acquired.
|
||||
|
@ -110,7 +83,7 @@ Lock
|
|||
|
||||
|
||||
Event
|
||||
^^^^^
|
||||
-----
|
||||
|
||||
.. class:: Event(\*, loop=None)
|
||||
|
||||
|
@ -151,7 +124,7 @@ Event
|
|||
|
||||
|
||||
Condition
|
||||
^^^^^^^^^
|
||||
---------
|
||||
|
||||
.. class:: Condition(lock=None, \*, loop=None)
|
||||
|
||||
|
@ -166,6 +139,9 @@ Condition
|
|||
object, and it is used as the underlying lock. Otherwise,
|
||||
a new :class:`Lock` object is created and used as the underlying lock.
|
||||
|
||||
Conditions support the :ref:`context management protocol
|
||||
<async-with-locks>`.
|
||||
|
||||
This class is :ref:`not thread safe <asyncio-multithreading>`.
|
||||
|
||||
.. coroutinemethod:: acquire()
|
||||
|
@ -239,11 +215,8 @@ Condition
|
|||
This method is a :ref:`coroutine <coroutine>`.
|
||||
|
||||
|
||||
Semaphores
|
||||
----------
|
||||
|
||||
Semaphore
|
||||
^^^^^^^^^
|
||||
---------
|
||||
|
||||
.. class:: Semaphore(value=1, \*, loop=None)
|
||||
|
||||
|
@ -254,12 +227,13 @@ Semaphore
|
|||
counter can never go below zero; when :meth:`acquire` finds that it is zero,
|
||||
it blocks, waiting until some other coroutine calls :meth:`release`.
|
||||
|
||||
Semaphores also support the context management protocol.
|
||||
|
||||
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 raised.
|
||||
|
||||
Semaphores support the :ref:`context management protocol
|
||||
<async-with-locks>`.
|
||||
|
||||
This class is :ref:`not thread safe <asyncio-multithreading>`.
|
||||
|
||||
.. coroutinemethod:: acquire()
|
||||
|
@ -285,7 +259,7 @@ Semaphore
|
|||
|
||||
|
||||
BoundedSemaphore
|
||||
^^^^^^^^^^^^^^^^
|
||||
----------------
|
||||
|
||||
.. class:: BoundedSemaphore(value=1, \*, loop=None)
|
||||
|
||||
|
@ -293,3 +267,39 @@ BoundedSemaphore
|
|||
|
||||
This raises :exc:`ValueError` in :meth:`~Semaphore.release` if it would
|
||||
increase the value above the initial value.
|
||||
|
||||
Bounded semapthores support the :ref:`context management
|
||||
protocol <async-with-locks>`.
|
||||
|
||||
This class is :ref:`not thread safe <asyncio-multithreading>`.
|
||||
|
||||
|
||||
.. _async-with-locks:
|
||||
|
||||
Using locks, conditions and semaphores in the :keyword:`async with` statement
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
:class:`Lock`, :class:`Condition`, :class:`Semaphore`, and
|
||||
:class:`BoundedSemaphore` objects can be used in :keyword:`async with`
|
||||
statements.
|
||||
|
||||
The :meth:`acquire` method will be called when the block is entered,
|
||||
and :meth:`release` will be called when the block is exited. Hence,
|
||||
the following snippet::
|
||||
|
||||
async with lock:
|
||||
# do something...
|
||||
|
||||
is equivalent to::
|
||||
|
||||
await lock.acquire()
|
||||
try:
|
||||
# do something...
|
||||
finally:
|
||||
lock.release()
|
||||
|
||||
.. deprecated:: 3.7
|
||||
|
||||
Lock acquiring using ``await lock`` or ``yield from lock`` and
|
||||
:keyword:`with` statement (``with await lock``, ``with (yield from
|
||||
lock)``) are deprecated.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue