mirror of
https://github.com/python/cpython.git
synced 2025-12-04 00:30:19 +00:00
bpo-32258: Replace 'yield from' to 'await' in asyncio docs (#4779)
* Replace 'yield from' to 'await' in asyncio docs * Fix docstrings
This commit is contained in:
parent
abae67ebc2
commit
8874342cf3
9 changed files with 79 additions and 82 deletions
|
|
@ -81,12 +81,11 @@ is called.
|
||||||
If you wait for a future, you should check early if the future was cancelled to
|
If you wait for a future, you should check early if the future was cancelled to
|
||||||
avoid useless operations. Example::
|
avoid useless operations. Example::
|
||||||
|
|
||||||
@coroutine
|
async def slow_operation(fut):
|
||||||
def slow_operation(fut):
|
|
||||||
if fut.cancelled():
|
if fut.cancelled():
|
||||||
return
|
return
|
||||||
# ... slow computation ...
|
# ... slow computation ...
|
||||||
yield from fut
|
await fut
|
||||||
# ...
|
# ...
|
||||||
|
|
||||||
The :func:`shield` function can also be used to ignore cancellation.
|
The :func:`shield` function can also be used to ignore cancellation.
|
||||||
|
|
@ -99,7 +98,7 @@ Concurrency and multithreading
|
||||||
|
|
||||||
An event loop runs in a thread and executes all callbacks and tasks in the same
|
An event loop runs in a thread and executes all callbacks and tasks in the same
|
||||||
thread. While a task is running in the event loop, no other task is running in
|
thread. While a task is running in the event loop, no other task is running in
|
||||||
the same thread. But when the task uses ``yield from``, the task is suspended
|
the same thread. But when the task uses ``await``, the task is suspended
|
||||||
and the event loop executes the next task.
|
and the event loop executes the next task.
|
||||||
|
|
||||||
To schedule a callback from a different thread, the
|
To schedule a callback from a different thread, the
|
||||||
|
|
@ -192,8 +191,7 @@ Example with the bug::
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def test():
|
||||||
def test():
|
|
||||||
print("never scheduled")
|
print("never scheduled")
|
||||||
|
|
||||||
test()
|
test()
|
||||||
|
|
@ -270,10 +268,9 @@ traceback where the task was created. Output in debug mode::
|
||||||
There are different options to fix this issue. The first option is to chain the
|
There are different options to fix this issue. The first option is to chain the
|
||||||
coroutine in another coroutine and use classic try/except::
|
coroutine in another coroutine and use classic try/except::
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def handle_exception():
|
||||||
def handle_exception():
|
|
||||||
try:
|
try:
|
||||||
yield from bug()
|
await bug()
|
||||||
except Exception:
|
except Exception:
|
||||||
print("exception consumed")
|
print("exception consumed")
|
||||||
|
|
||||||
|
|
@ -300,7 +297,7 @@ Chain coroutines correctly
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
When a coroutine function calls other coroutine functions and tasks, they
|
When a coroutine function calls other coroutine functions and tasks, they
|
||||||
should be chained explicitly with ``yield from``. Otherwise, the execution is
|
should be chained explicitly with ``await``. Otherwise, the execution is
|
||||||
not guaranteed to be sequential.
|
not guaranteed to be sequential.
|
||||||
|
|
||||||
Example with different bugs using :func:`asyncio.sleep` to simulate slow
|
Example with different bugs using :func:`asyncio.sleep` to simulate slow
|
||||||
|
|
@ -308,26 +305,22 @@ operations::
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def create():
|
||||||
def create():
|
await asyncio.sleep(3.0)
|
||||||
yield from asyncio.sleep(3.0)
|
|
||||||
print("(1) create file")
|
print("(1) create file")
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def write():
|
||||||
def write():
|
await asyncio.sleep(1.0)
|
||||||
yield from asyncio.sleep(1.0)
|
|
||||||
print("(2) write into file")
|
print("(2) write into file")
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def close():
|
||||||
def close():
|
|
||||||
print("(3) close file")
|
print("(3) close file")
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def test():
|
||||||
def test():
|
|
||||||
asyncio.ensure_future(create())
|
asyncio.ensure_future(create())
|
||||||
asyncio.ensure_future(write())
|
asyncio.ensure_future(write())
|
||||||
asyncio.ensure_future(close())
|
asyncio.ensure_future(close())
|
||||||
yield from asyncio.sleep(2.0)
|
await asyncio.sleep(2.0)
|
||||||
loop.stop()
|
loop.stop()
|
||||||
|
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
|
|
@ -359,24 +352,22 @@ The loop stopped before the ``create()`` finished, ``close()`` has been called
|
||||||
before ``write()``, whereas coroutine functions were called in this order:
|
before ``write()``, whereas coroutine functions were called in this order:
|
||||||
``create()``, ``write()``, ``close()``.
|
``create()``, ``write()``, ``close()``.
|
||||||
|
|
||||||
To fix the example, tasks must be marked with ``yield from``::
|
To fix the example, tasks must be marked with ``await``::
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def test():
|
||||||
def test():
|
await asyncio.ensure_future(create())
|
||||||
yield from asyncio.ensure_future(create())
|
await asyncio.ensure_future(write())
|
||||||
yield from asyncio.ensure_future(write())
|
await asyncio.ensure_future(close())
|
||||||
yield from asyncio.ensure_future(close())
|
await asyncio.sleep(2.0)
|
||||||
yield from asyncio.sleep(2.0)
|
|
||||||
loop.stop()
|
loop.stop()
|
||||||
|
|
||||||
Or without ``asyncio.ensure_future()``::
|
Or without ``asyncio.ensure_future()``::
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def test():
|
||||||
def test():
|
await create()
|
||||||
yield from create()
|
await write()
|
||||||
yield from write()
|
await close()
|
||||||
yield from close()
|
await asyncio.sleep(2.0)
|
||||||
yield from asyncio.sleep(2.0)
|
|
||||||
loop.stop()
|
loop.stop()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -488,8 +488,9 @@ Coroutines can be scheduled in a protocol method using :func:`ensure_future`,
|
||||||
but there is no guarantee made about the execution order. Protocols are not
|
but there is no guarantee made about the execution order. Protocols are not
|
||||||
aware of coroutines created in protocol methods and so will not wait for them.
|
aware of coroutines created in protocol methods and so will not wait for them.
|
||||||
|
|
||||||
To have a reliable execution order, use :ref:`stream objects <asyncio-streams>` in a
|
To have a reliable execution order,
|
||||||
coroutine with ``yield from``. For example, the :meth:`StreamWriter.drain`
|
use :ref:`stream objects <asyncio-streams>` in a
|
||||||
|
coroutine with ``await``. For example, the :meth:`StreamWriter.drain`
|
||||||
coroutine can be used to wait until the write buffer is flushed.
|
coroutine can be used to wait until the write buffer is flushed.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -589,7 +590,7 @@ received data and close the connection::
|
||||||
|
|
||||||
:meth:`Transport.close` can be called immediately after
|
:meth:`Transport.close` can be called immediately after
|
||||||
:meth:`WriteTransport.write` even if data are not sent yet on the socket: both
|
:meth:`WriteTransport.write` even if data are not sent yet on the socket: both
|
||||||
methods are asynchronous. ``yield from`` is not needed because these transport
|
methods are asynchronous. ``await`` is not needed because these transport
|
||||||
methods are not coroutines.
|
methods are not coroutines.
|
||||||
|
|
||||||
.. seealso::
|
.. seealso::
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ Queue
|
||||||
A queue, useful for coordinating producer and consumer coroutines.
|
A queue, useful for coordinating producer and consumer coroutines.
|
||||||
|
|
||||||
If *maxsize* is less than or equal to zero, the queue size is infinite. If
|
If *maxsize* is less than or equal to zero, the queue size is infinite. If
|
||||||
it is an integer greater than ``0``, then ``yield from put()`` will block
|
it is an integer greater than ``0``, then ``await put()`` will block
|
||||||
when the queue reaches *maxsize*, until an item is removed by :meth:`get`.
|
when the queue reaches *maxsize*, until an item is removed by :meth:`get`.
|
||||||
|
|
||||||
Unlike the standard library :mod:`queue`, you can reliably know this Queue's
|
Unlike the standard library :mod:`queue`, you can reliably know this Queue's
|
||||||
|
|
|
||||||
|
|
@ -208,7 +208,7 @@ StreamWriter
|
||||||
The intended use is to write::
|
The intended use is to write::
|
||||||
|
|
||||||
w.write(data)
|
w.write(data)
|
||||||
yield from w.drain()
|
await w.drain()
|
||||||
|
|
||||||
When the size of the transport buffer reaches the high-water limit (the
|
When the size of the transport buffer reaches the high-water limit (the
|
||||||
protocol is paused), block until the size of the buffer is drained down
|
protocol is paused), block until the size of the buffer is drained down
|
||||||
|
|
@ -301,15 +301,14 @@ TCP echo client using the :func:`asyncio.open_connection` function::
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def tcp_echo_client(message, loop):
|
||||||
def tcp_echo_client(message, loop):
|
reader, writer = await asyncio.open_connection('127.0.0.1', 8888,
|
||||||
reader, writer = yield from asyncio.open_connection('127.0.0.1', 8888,
|
loop=loop)
|
||||||
loop=loop)
|
|
||||||
|
|
||||||
print('Send: %r' % message)
|
print('Send: %r' % message)
|
||||||
writer.write(message.encode())
|
writer.write(message.encode())
|
||||||
|
|
||||||
data = yield from reader.read(100)
|
data = await reader.read(100)
|
||||||
print('Received: %r' % data.decode())
|
print('Received: %r' % data.decode())
|
||||||
|
|
||||||
print('Close the socket')
|
print('Close the socket')
|
||||||
|
|
@ -335,16 +334,15 @@ TCP echo server using the :func:`asyncio.start_server` function::
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def handle_echo(reader, writer):
|
||||||
def handle_echo(reader, writer):
|
data = await reader.read(100)
|
||||||
data = yield from reader.read(100)
|
|
||||||
message = data.decode()
|
message = data.decode()
|
||||||
addr = writer.get_extra_info('peername')
|
addr = writer.get_extra_info('peername')
|
||||||
print("Received %r from %r" % (message, addr))
|
print("Received %r from %r" % (message, addr))
|
||||||
|
|
||||||
print("Send: %r" % message)
|
print("Send: %r" % message)
|
||||||
writer.write(data)
|
writer.write(data)
|
||||||
yield from writer.drain()
|
await writer.drain()
|
||||||
|
|
||||||
print("Close the client socket")
|
print("Close the client socket")
|
||||||
writer.close()
|
writer.close()
|
||||||
|
|
@ -387,13 +385,13 @@ Simple example querying HTTP headers of the URL passed on the command line::
|
||||||
connect = asyncio.open_connection(url.hostname, 443, ssl=True)
|
connect = asyncio.open_connection(url.hostname, 443, ssl=True)
|
||||||
else:
|
else:
|
||||||
connect = asyncio.open_connection(url.hostname, 80)
|
connect = asyncio.open_connection(url.hostname, 80)
|
||||||
reader, writer = yield from connect
|
reader, writer = await connect
|
||||||
query = ('HEAD {path} HTTP/1.0\r\n'
|
query = ('HEAD {path} HTTP/1.0\r\n'
|
||||||
'Host: {hostname}\r\n'
|
'Host: {hostname}\r\n'
|
||||||
'\r\n').format(path=url.path or '/', hostname=url.hostname)
|
'\r\n').format(path=url.path or '/', hostname=url.hostname)
|
||||||
writer.write(query.encode('latin-1'))
|
writer.write(query.encode('latin-1'))
|
||||||
while True:
|
while True:
|
||||||
line = yield from reader.readline()
|
line = await reader.readline()
|
||||||
if not line:
|
if not line:
|
||||||
break
|
break
|
||||||
line = line.decode('latin1').rstrip()
|
line = line.decode('latin1').rstrip()
|
||||||
|
|
@ -428,19 +426,18 @@ Coroutine waiting until a socket receives data using the
|
||||||
import asyncio
|
import asyncio
|
||||||
from socket import socketpair
|
from socket import socketpair
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def wait_for_data(loop):
|
||||||
def wait_for_data(loop):
|
|
||||||
# Create a pair of connected sockets
|
# Create a pair of connected sockets
|
||||||
rsock, wsock = socketpair()
|
rsock, wsock = socketpair()
|
||||||
|
|
||||||
# Register the open socket to wait for data
|
# Register the open socket to wait for data
|
||||||
reader, writer = yield from asyncio.open_connection(sock=rsock, loop=loop)
|
reader, writer = await asyncio.open_connection(sock=rsock, loop=loop)
|
||||||
|
|
||||||
# Simulate the reception of data from the network
|
# Simulate the reception of data from the network
|
||||||
loop.call_soon(wsock.send, 'abc'.encode())
|
loop.call_soon(wsock.send, 'abc'.encode())
|
||||||
|
|
||||||
# Wait for data
|
# Wait for data
|
||||||
data = yield from reader.read(100)
|
data = await reader.read(100)
|
||||||
|
|
||||||
# Got data, we are done: close the socket
|
# Got data, we are done: close the socket
|
||||||
print("Received:", data.decode())
|
print("Received:", data.decode())
|
||||||
|
|
|
||||||
|
|
@ -347,21 +347,20 @@ wait for the subprocess exit. The subprocess is created by the
|
||||||
def process_exited(self):
|
def process_exited(self):
|
||||||
self.exit_future.set_result(True)
|
self.exit_future.set_result(True)
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def get_date(loop):
|
||||||
def get_date(loop):
|
|
||||||
code = 'import datetime; print(datetime.datetime.now())'
|
code = 'import datetime; print(datetime.datetime.now())'
|
||||||
exit_future = asyncio.Future(loop=loop)
|
exit_future = asyncio.Future(loop=loop)
|
||||||
|
|
||||||
# Create the subprocess controlled by the protocol DateProtocol,
|
# Create the subprocess controlled by the protocol DateProtocol,
|
||||||
# redirect the standard output into a pipe
|
# redirect the standard output into a pipe
|
||||||
create = loop.subprocess_exec(lambda: DateProtocol(exit_future),
|
transport, protocol = await loop.subprocess_exec(
|
||||||
sys.executable, '-c', code,
|
lambda: DateProtocol(exit_future),
|
||||||
stdin=None, stderr=None)
|
sys.executable, '-c', code,
|
||||||
transport, protocol = yield from create
|
stdin=None, stderr=None)
|
||||||
|
|
||||||
# Wait for the subprocess exit using the process_exited() method
|
# Wait for the subprocess exit using the process_exited() method
|
||||||
# of the protocol
|
# of the protocol
|
||||||
yield from exit_future
|
await exit_future
|
||||||
|
|
||||||
# Close the stdout pipe
|
# Close the stdout pipe
|
||||||
transport.close()
|
transport.close()
|
||||||
|
|
@ -398,16 +397,16 @@ function::
|
||||||
code = 'import datetime; print(datetime.datetime.now())'
|
code = 'import datetime; print(datetime.datetime.now())'
|
||||||
|
|
||||||
# Create the subprocess, redirect the standard output into a pipe
|
# Create the subprocess, redirect the standard output into a pipe
|
||||||
create = asyncio.create_subprocess_exec(sys.executable, '-c', code,
|
proc = await asyncio.create_subprocess_exec(
|
||||||
stdout=asyncio.subprocess.PIPE)
|
sys.executable, '-c', code,
|
||||||
proc = yield from create
|
stdout=asyncio.subprocess.PIPE)
|
||||||
|
|
||||||
# Read one line of output
|
# Read one line of output
|
||||||
data = yield from proc.stdout.readline()
|
data = await proc.stdout.readline()
|
||||||
line = data.decode('ascii').rstrip()
|
line = data.decode('ascii').rstrip()
|
||||||
|
|
||||||
# Wait for the subprocess exit
|
# Wait for the subprocess exit
|
||||||
yield from proc.wait()
|
await proc.wait()
|
||||||
return line
|
return line
|
||||||
|
|
||||||
if sys.platform == "win32":
|
if sys.platform == "win32":
|
||||||
|
|
|
||||||
|
|
@ -515,7 +515,7 @@ Task functions
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
for f in as_completed(fs):
|
for f in as_completed(fs):
|
||||||
result = yield from f # The 'yield from' may raise
|
result = await f # The 'await' may raise
|
||||||
# Use result
|
# Use result
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
@ -630,11 +630,11 @@ Task functions
|
||||||
|
|
||||||
The statement::
|
The statement::
|
||||||
|
|
||||||
res = yield from shield(something())
|
res = await shield(something())
|
||||||
|
|
||||||
is exactly equivalent to the statement::
|
is exactly equivalent to the statement::
|
||||||
|
|
||||||
res = yield from something()
|
res = await something()
|
||||||
|
|
||||||
*except* that if the coroutine containing it is cancelled, the task running
|
*except* that if the coroutine containing it is cancelled, the task running
|
||||||
in ``something()`` is not cancelled. From the point of view of
|
in ``something()`` is not cancelled. From the point of view of
|
||||||
|
|
@ -647,7 +647,7 @@ Task functions
|
||||||
combine ``shield()`` with a try/except clause, as follows::
|
combine ``shield()`` with a try/except clause, as follows::
|
||||||
|
|
||||||
try:
|
try:
|
||||||
res = yield from shield(something())
|
res = await shield(something())
|
||||||
except CancelledError:
|
except CancelledError:
|
||||||
res = None
|
res = None
|
||||||
|
|
||||||
|
|
@ -690,7 +690,7 @@ Task functions
|
||||||
|
|
||||||
Usage::
|
Usage::
|
||||||
|
|
||||||
done, pending = yield from asyncio.wait(fs)
|
done, pending = await asyncio.wait(fs)
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
|
@ -714,7 +714,7 @@ Task functions
|
||||||
|
|
||||||
This function is a :ref:`coroutine <coroutine>`, usage::
|
This function is a :ref:`coroutine <coroutine>`, usage::
|
||||||
|
|
||||||
result = yield from asyncio.wait_for(fut, 60.0)
|
result = await asyncio.wait_for(fut, 60.0)
|
||||||
|
|
||||||
.. versionchanged:: 3.4.3
|
.. versionchanged:: 3.4.3
|
||||||
If the wait is cancelled, the future *fut* is now also cancelled.
|
If the wait is cancelled, the future *fut* is now also cancelled.
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,9 @@ def _is_debug_mode():
|
||||||
# If you set _DEBUG to true, @coroutine will wrap the resulting
|
# If you set _DEBUG to true, @coroutine will wrap the resulting
|
||||||
# generator objects in a CoroWrapper instance (defined below). That
|
# generator objects in a CoroWrapper instance (defined below). That
|
||||||
# instance will log a message when the generator is never iterated
|
# instance will log a message when the generator is never iterated
|
||||||
# over, which may happen when you forget to use "yield from" with a
|
# over, which may happen when you forget to use "await" or "yield from"
|
||||||
# coroutine call. Note that the value of the _DEBUG flag is taken
|
# with a coroutine call.
|
||||||
|
# Note that the value of the _DEBUG flag is taken
|
||||||
# when the decorator is used, so to be of any use it must be set
|
# when the decorator is used, so to be of any use it must be set
|
||||||
# before you define your coroutines. A downside of using this feature
|
# before you define your coroutines. A downside of using this feature
|
||||||
# is that tracebacks show entries for the CoroWrapper.__next__ method
|
# is that tracebacks show entries for the CoroWrapper.__next__ method
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,8 @@ class Future:
|
||||||
# The value must also be not-None, to enable a subclass to declare
|
# The value must also be not-None, to enable a subclass to declare
|
||||||
# that it is not compatible by setting this to None.
|
# that it is not compatible by setting this to None.
|
||||||
# - It is set by __iter__() below so that Task._step() can tell
|
# - It is set by __iter__() below so that Task._step() can tell
|
||||||
# the difference between `yield from Future()` (correct) vs.
|
# the difference between
|
||||||
|
# `await Future()` or`yield from Future()` (correct) vs.
|
||||||
# `yield Future()` (incorrect).
|
# `yield Future()` (incorrect).
|
||||||
_asyncio_future_blocking = False
|
_asyncio_future_blocking = False
|
||||||
|
|
||||||
|
|
@ -236,7 +237,7 @@ class Future:
|
||||||
if not self.done():
|
if not self.done():
|
||||||
self._asyncio_future_blocking = True
|
self._asyncio_future_blocking = True
|
||||||
yield self # This tells Task to wait for completion.
|
yield self # This tells Task to wait for completion.
|
||||||
assert self.done(), "yield from wasn't used with future"
|
assert self.done(), "await wasn't used with future"
|
||||||
return self.result() # May raise too.
|
return self.result() # May raise too.
|
||||||
|
|
||||||
__await__ = __iter__ # make compatible with 'await' expression
|
__await__ = __iter__ # make compatible with 'await' expression
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,10 @@ class _ContextManager:
|
||||||
|
|
||||||
with lock:
|
with lock:
|
||||||
<block>
|
<block>
|
||||||
|
|
||||||
|
Deprecated, use 'async with' statement:
|
||||||
|
async with lock:
|
||||||
|
<block>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, lock):
|
def __init__(self, lock):
|
||||||
|
|
@ -64,6 +68,9 @@ class _ContextManagerMixin:
|
||||||
# <block>
|
# <block>
|
||||||
# finally:
|
# finally:
|
||||||
# lock.release()
|
# lock.release()
|
||||||
|
# Deprecated, use 'async with' statement:
|
||||||
|
# async with lock:
|
||||||
|
# <block>
|
||||||
warnings.warn("'with (yield from lock)' is deprecated "
|
warnings.warn("'with (yield from lock)' is deprecated "
|
||||||
"use 'async with lock' instead",
|
"use 'async with lock' instead",
|
||||||
DeprecationWarning, stacklevel=2)
|
DeprecationWarning, stacklevel=2)
|
||||||
|
|
@ -113,16 +120,16 @@ class Lock(_ContextManagerMixin):
|
||||||
release() call resets the state to unlocked; first coroutine which
|
release() call resets the state to unlocked; first coroutine which
|
||||||
is blocked in acquire() is being processed.
|
is blocked in acquire() is being processed.
|
||||||
|
|
||||||
acquire() is a coroutine and should be called with 'yield from'.
|
acquire() is a coroutine and should be called with 'await'.
|
||||||
|
|
||||||
Locks also support the context management protocol. '(yield from lock)'
|
Locks also support the asynchronous context management protocol.
|
||||||
should be used as the context manager expression.
|
'async with lock' statement should be used.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
lock = Lock()
|
lock = Lock()
|
||||||
...
|
...
|
||||||
yield from lock
|
await lock.acquire()
|
||||||
try:
|
try:
|
||||||
...
|
...
|
||||||
finally:
|
finally:
|
||||||
|
|
@ -132,13 +139,13 @@ class Lock(_ContextManagerMixin):
|
||||||
|
|
||||||
lock = Lock()
|
lock = Lock()
|
||||||
...
|
...
|
||||||
with (yield from lock):
|
async with lock:
|
||||||
...
|
...
|
||||||
|
|
||||||
Lock objects can be tested for locking state:
|
Lock objects can be tested for locking state:
|
||||||
|
|
||||||
if not lock.locked():
|
if not lock.locked():
|
||||||
yield from lock
|
await lock.acquire()
|
||||||
else:
|
else:
|
||||||
# lock is acquired
|
# lock is acquired
|
||||||
...
|
...
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue