]> granicus.if.org Git - python/commitdiff
bpo-32258: Replace 'yield from' to 'await' in asyncio docs (#4779)
authorAndrew Svetlov <andrew.svetlov@gmail.com>
Mon, 11 Dec 2017 15:35:49 +0000 (17:35 +0200)
committerGitHub <noreply@github.com>
Mon, 11 Dec 2017 15:35:49 +0000 (17:35 +0200)
* Replace 'yield from' to 'await' in asyncio docs

* Fix docstrings

Doc/library/asyncio-dev.rst
Doc/library/asyncio-protocol.rst
Doc/library/asyncio-queue.rst
Doc/library/asyncio-stream.rst
Doc/library/asyncio-subprocess.rst
Doc/library/asyncio-task.rst
Lib/asyncio/coroutines.py
Lib/asyncio/futures.py
Lib/asyncio/locks.py

index b9735de2078d18a3f6790be64c3ffd76e49605b9..100fff561c5b1a17428ea839da7d409910f5474b 100644 (file)
@@ -81,12 +81,11 @@ is called.
 If you wait for a future, you should check early if the future was cancelled to
 avoid useless operations. Example::
 
-    @coroutine
-    def slow_operation(fut):
+    async def slow_operation(fut):
         if fut.cancelled():
             return
         # ... slow computation ...
-        yield from fut
+        await fut
         # ...
 
 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
 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.
 
 To schedule a callback from a different thread, the
@@ -192,8 +191,7 @@ Example with the bug::
 
     import asyncio
 
-    @asyncio.coroutine
-    def test():
+    async def test():
         print("never scheduled")
 
     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
 coroutine in another coroutine and use classic try/except::
 
-    @asyncio.coroutine
-    def handle_exception():
+    async def handle_exception():
         try:
-            yield from bug()
+            await bug()
         except Exception:
             print("exception consumed")
 
@@ -300,7 +297,7 @@ Chain coroutines correctly
 --------------------------
 
 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.
 
 Example with different bugs using :func:`asyncio.sleep` to simulate slow
@@ -308,26 +305,22 @@ operations::
 
     import asyncio
 
-    @asyncio.coroutine
-    def create():
-        yield from asyncio.sleep(3.0)
+    async def create():
+        await asyncio.sleep(3.0)
         print("(1) create file")
 
-    @asyncio.coroutine
-    def write():
-        yield from asyncio.sleep(1.0)
+    async def write():
+        await asyncio.sleep(1.0)
         print("(2) write into file")
 
-    @asyncio.coroutine
-    def close():
+    async def close():
         print("(3) close file")
 
-    @asyncio.coroutine
-    def test():
+    async def test():
         asyncio.ensure_future(create())
         asyncio.ensure_future(write())
         asyncio.ensure_future(close())
-        yield from asyncio.sleep(2.0)
+        await asyncio.sleep(2.0)
         loop.stop()
 
     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:
 ``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
-    def test():
-        yield from asyncio.ensure_future(create())
-        yield from asyncio.ensure_future(write())
-        yield from asyncio.ensure_future(close())
-        yield from asyncio.sleep(2.0)
+    async def test():
+        await asyncio.ensure_future(create())
+        await asyncio.ensure_future(write())
+        await asyncio.ensure_future(close())
+        await asyncio.sleep(2.0)
         loop.stop()
 
 Or without ``asyncio.ensure_future()``::
 
-    @asyncio.coroutine
-    def test():
-        yield from create()
-        yield from write()
-        yield from close()
-        yield from asyncio.sleep(2.0)
+    async def test():
+        await create()
+        await write()
+        await close()
+        await asyncio.sleep(2.0)
         loop.stop()
 
 
index af462009fa8f038e4a26ad28d5cefdf8ad14d3c0..a4b0d594933ced7f4d5de3133e1195a2a1c93077 100644 (file)
@@ -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
 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
-coroutine with ``yield from``. For example, the :meth:`StreamWriter.drain`
+To have a reliable execution order,
+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.
 
 
@@ -589,7 +590,7 @@ received data and close the connection::
 
 :meth:`Transport.close` can be called immediately after
 :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.
 
 .. seealso::
index ea78755008244d82578ada2680d31a74f833db75..65497f29d895d0a082105be5c22b0c3af60ff8a4 100644 (file)
@@ -24,7 +24,7 @@ Queue
    A queue, useful for coordinating producer and consumer coroutines.
 
    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`.
 
    Unlike the standard library :mod:`queue`, you can reliably know this Queue's
index 78091d62a71631b828602b79920c89ef911172be..6d5cbbc5bd533d7ab8ae01a9bf9e65997846a9e1 100644 (file)
@@ -208,7 +208,7 @@ StreamWriter
       The intended use is to write::
 
           w.write(data)
-          yield from w.drain()
+          await w.drain()
 
       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
@@ -301,15 +301,14 @@ TCP echo client using the :func:`asyncio.open_connection` function::
 
     import asyncio
 
-    @asyncio.coroutine
-    def tcp_echo_client(message, loop):
-        reader, writer = yield from asyncio.open_connection('127.0.0.1', 8888,
-                                                            loop=loop)
+    async def tcp_echo_client(message, loop):
+        reader, writer = await asyncio.open_connection('127.0.0.1', 8888,
+                                                       loop=loop)
 
         print('Send: %r' % message)
         writer.write(message.encode())
 
-        data = yield from reader.read(100)
+        data = await reader.read(100)
         print('Received: %r' % data.decode())
 
         print('Close the socket')
@@ -335,16 +334,15 @@ TCP echo server using the :func:`asyncio.start_server` function::
 
     import asyncio
 
-    @asyncio.coroutine
-    def handle_echo(reader, writer):
-        data = yield from reader.read(100)
+    async def handle_echo(reader, writer):
+        data = await reader.read(100)
         message = data.decode()
         addr = writer.get_extra_info('peername')
         print("Received %r from %r" % (message, addr))
 
         print("Send: %r" % message)
         writer.write(data)
-        yield from writer.drain()
+        await writer.drain()
 
         print("Close the client socket")
         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)
         else:
             connect = asyncio.open_connection(url.hostname, 80)
-        reader, writer = yield from connect
+        reader, writer = await connect
         query = ('HEAD {path} HTTP/1.0\r\n'
                  'Host: {hostname}\r\n'
                  '\r\n').format(path=url.path or '/', hostname=url.hostname)
         writer.write(query.encode('latin-1'))
         while True:
-            line = yield from reader.readline()
+            line = await reader.readline()
             if not line:
                 break
             line = line.decode('latin1').rstrip()
@@ -428,19 +426,18 @@ Coroutine waiting until a socket receives data using the
     import asyncio
     from socket import socketpair
 
-    @asyncio.coroutine
-    def wait_for_data(loop):
+    async def wait_for_data(loop):
         # Create a pair of connected sockets
         rsock, wsock = socketpair()
 
         # 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
         loop.call_soon(wsock.send, 'abc'.encode())
 
         # Wait for data
-        data = yield from reader.read(100)
+        data = await reader.read(100)
 
         # Got data, we are done: close the socket
         print("Received:", data.decode())
index 1c1d0be918da74cc7224b9c7a19e4f522b111dff..280b76400374cbd5c13b6aea677ef06a84f2b339 100644 (file)
@@ -347,21 +347,20 @@ wait for the subprocess exit. The subprocess is created by the
         def process_exited(self):
             self.exit_future.set_result(True)
 
-    @asyncio.coroutine
-    def get_date(loop):
+    async def get_date(loop):
         code = 'import datetime; print(datetime.datetime.now())'
         exit_future = asyncio.Future(loop=loop)
 
         # Create the subprocess controlled by the protocol DateProtocol,
         # redirect the standard output into a pipe
-        create = loop.subprocess_exec(lambda: DateProtocol(exit_future),
-                                      sys.executable, '-c', code,
-                                      stdin=None, stderr=None)
-        transport, protocol = yield from create
+        transport, protocol = await loop.subprocess_exec(
+            lambda: DateProtocol(exit_future),
+            sys.executable, '-c', code,
+            stdin=None, stderr=None)
 
         # Wait for the subprocess exit using the process_exited() method
         # of the protocol
-        yield from exit_future
+        await exit_future
 
         # Close the stdout pipe
         transport.close()
@@ -398,16 +397,16 @@ function::
         code = 'import datetime; print(datetime.datetime.now())'
 
         # Create the subprocess, redirect the standard output into a pipe
-        create = asyncio.create_subprocess_exec(sys.executable, '-c', code,
-                                                stdout=asyncio.subprocess.PIPE)
-        proc = yield from create
+        proc = await asyncio.create_subprocess_exec(
+            sys.executable, '-c', code,
+            stdout=asyncio.subprocess.PIPE)
 
         # Read one line of output
-        data = yield from proc.stdout.readline()
+        data = await proc.stdout.readline()
         line = data.decode('ascii').rstrip()
 
         # Wait for the subprocess exit
-        yield from proc.wait()
+        await proc.wait()
         return line
 
     if sys.platform == "win32":
index 3656f793debd66f96b239ba717cb61bb7ce09682..a8a0a8e85efe72b9560f67501d9f859dde7964ab 100644 (file)
@@ -515,7 +515,7 @@ Task functions
    Example::
 
        for f in as_completed(fs):
-           result = yield from f  # The 'yield from' may raise
+           result = await f  # The 'await' may raise
            # Use result
 
    .. note::
@@ -630,11 +630,11 @@ Task functions
 
    The statement::
 
-       res = yield from shield(something())
+       res = await shield(something())
 
    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
    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::
 
        try:
-           res = yield from shield(something())
+           res = await shield(something())
        except CancelledError:
            res = None
 
@@ -690,7 +690,7 @@ Task functions
 
    Usage::
 
-        done, pending = yield from asyncio.wait(fs)
+        done, pending = await asyncio.wait(fs)
 
    .. note::
 
@@ -714,7 +714,7 @@ Task functions
 
    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
       If the wait is cancelled, the future *fut* is now also cancelled.
index d7e6b4c1ccbe4187e2417493eb0043c68235a36b..bca7fe3a53742d2ca2bddac46f6958683681be9f 100644 (file)
@@ -19,8 +19,9 @@ def _is_debug_mode():
     # If you set _DEBUG to true, @coroutine will wrap the resulting
     # generator objects in a CoroWrapper instance (defined below).  That
     # instance will log a message when the generator is never iterated
-    # over, which may happen when you forget to use "yield from" with a
-    # coroutine call.  Note that the value of the _DEBUG flag is taken
+    # over, which may happen when you forget to use "await" or "yield from"
+    # 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
     # before you define your coroutines.  A downside of using this feature
     # is that tracebacks show entries for the CoroWrapper.__next__ method
index b805f99896d95ef4efe4827e02ecbc4162dca089..d46a295197b8766890011ae4748eb7c3801befe2 100644 (file)
@@ -59,7 +59,8 @@ class Future:
     #   The value must also be not-None, to enable a subclass to declare
     #   that it is not compatible by setting this to None.
     # - 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).
     _asyncio_future_blocking = False
 
@@ -236,7 +237,7 @@ class Future:
         if not self.done():
             self._asyncio_future_blocking = True
             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.
 
     __await__ = __iter__  # make compatible with 'await' expression
index 54f62585983e9c96bee32e0ac43ea967e920c382..61938373509678da94cf1d4a7ceea13bc07eeff2 100644 (file)
@@ -23,6 +23,10 @@ class _ContextManager:
 
         with lock:
             <block>
+
+    Deprecated, use 'async with' statement:
+        async with lock:
+            <block>
     """
 
     def __init__(self, lock):
@@ -64,6 +68,9 @@ class _ContextManagerMixin:
         #         <block>
         #     finally:
         #         lock.release()
+        # Deprecated, use 'async with' statement:
+        #     async with lock:
+        #         <block>
         warnings.warn("'with (yield from lock)' is deprecated "
                       "use 'async with lock' instead",
                       DeprecationWarning, stacklevel=2)
@@ -113,16 +120,16 @@ class Lock(_ContextManagerMixin):
     release() call resets the state to unlocked; first coroutine which
     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)'
-    should be used as the context manager expression.
+    Locks also support the asynchronous context management protocol.
+    'async with lock' statement should be used.
 
     Usage:
 
         lock = Lock()
         ...
-        yield from lock
+        await lock.acquire()
         try:
             ...
         finally:
@@ -132,13 +139,13 @@ class Lock(_ContextManagerMixin):
 
         lock = Lock()
         ...
-        with (yield from lock):
+        async with lock:
              ...
 
     Lock objects can be tested for locking state:
 
         if not lock.locked():
-           yield from lock
+           await lock.acquire()
         else:
            # lock is acquired
            ...