summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYury Selivanov <yury@magic.io>2018-09-14 20:32:07 (GMT)
committerCarol Willing <carolcode@willingconsulting.com>2018-09-14 20:32:07 (GMT)
commit3faaa8857a42a36383bb18425444e597fc876797 (patch)
tree109c2997624aba5ed64b619938a6ca8a7bf007c1
parentad8a0004206ba7aec5a8a60fce413da718080db2 (diff)
downloadcpython-3faaa8857a42a36383bb18425444e597fc876797.zip
cpython-3faaa8857a42a36383bb18425444e597fc876797.tar.gz
cpython-3faaa8857a42a36383bb18425444e597fc876797.tar.bz2
bpo-33649: Refresh Tasks and Futures pages (#9314)
* bpo-33649: Refresh Tasks and Futures pages * Fixes * Fix markup
-rw-r--r--Doc/library/asyncio-eventloop.rst2
-rw-r--r--Doc/library/asyncio-future.rst240
-rw-r--r--Doc/library/asyncio-protocol.rst18
-rw-r--r--Doc/library/asyncio-task.rst1045
-rw-r--r--Doc/library/asyncio.rst49
5 files changed, 759 insertions, 595 deletions
diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst
index baa5234..e1b47d2 100644
--- a/Doc/library/asyncio-eventloop.rst
+++ b/Doc/library/asyncio-eventloop.rst
@@ -1429,7 +1429,7 @@ event loop::
.. seealso::
- A similar :ref:`Hello World <asyncio-hello-world-coroutine>`
+ A similar :ref:`Hello World <coroutine>`
example created with a coroutine and the :func:`run` function.
diff --git a/Doc/library/asyncio-future.rst b/Doc/library/asyncio-future.rst
new file mode 100644
index 0000000..2c41c1c
--- /dev/null
+++ b/Doc/library/asyncio-future.rst
@@ -0,0 +1,240 @@
+.. currentmodule:: asyncio
+
+
+=======
+Futures
+=======
+
+*Future* objects are used to bridge low-level callback-based code
+with high-level async/await code.
+
+
+Future Functions
+================
+
+.. function:: isfuture(obj)
+
+ Return ``True`` if *obj* is either of:
+
+ * an instance of :class:`asyncio.Future`,
+ * an instance of :class:`asyncio.Task`,
+ * a Future-like object with a ``_asyncio_future_blocking``
+ attribute.
+
+ .. versionadded:: 3.5
+
+
+.. function:: ensure_future(obj, \*, loop=None)
+
+ Return:
+
+ * *obj* argument as is, if *obj* is a :class:`Future`,
+ a :class:`Task`, or a Future-like object (:func:`isfuture`
+ is used for the test.)
+
+ * a :class:`Task` object wrapping *obj*, if *obj* is a
+ coroutine (:func:`iscoroutine` is used for the test.)
+
+ * a :class:`Task` object that would await on *obj*, if *obj* is an
+ awaitable (:func:`inspect.isawaitable` is used for the test.)
+
+ If *obj* is neither of the above a :exc:`TypeError` is raised.
+
+ .. important::
+
+ See also the :func:`create_task` function which is the
+ preferred way for creating new Tasks.
+
+ .. versionchanged:: 3.5.1
+ The function accepts any :term:`awaitable` object.
+
+
+.. function:: wrap_future(future, \*, loop=None)
+
+ Wrap a :class:`concurrent.futures.Future` object in a
+ :class:`asyncio.Future` object.
+
+
+Future Object
+=============
+
+.. class:: Future(\*, loop=None)
+
+ A Future represents an eventual result of an asynchronous
+ operation. Not thread-safe.
+
+ Future is an :term:`awaitable` object. Coroutines can await on
+ Future objects until they either have a result or an exception
+ set, or until they are cancelled.
+
+ Typically Futures are used to enable low-level
+ callback-based code (e.g. in protocols implemented using asyncio
+ :ref:`transports <asyncio-transports-protocols>`)
+ to interoperate with high-level async/await code.
+
+ The rule of thumb is to never expose Future objects in user-facing
+ APIs, and the recommended way to create a Future object is to call
+ :meth:`loop.create_future`. This way alternative event loop
+ implementations can inject their own optimized implementations
+ of a Future object.
+
+ .. versionchanged:: 3.7
+ Added support for the :mod:`contextvars` module.
+
+ .. method:: result()
+
+ Return the result of the Future.
+
+ If the Future is *done* and has a result set by the
+ :meth:`set_result` method, the result value is returned.
+
+ If the Future is *done* and has an exception set by the
+ :meth:`set_exception` method, this method raises the exception.
+
+ If the Future has been *cancelled*, this method raises
+ a :exc:`CancelledError` exception.
+
+ If the Future's result isn't yet available, this method raises
+ a :exc:`InvalidStateError` exception.
+
+ .. method:: set_result(result)
+
+ Mark the Future as *done* and set its result.
+
+ Raises a :exc:`InvalidStateError` error if the Future is
+ already *done*.
+
+ .. method:: set_exception(exception)
+
+ Mark the Future as *done* and set an exception.
+
+ Raises a :exc:`InvalidStateError` error if the Future is
+ already *done*.
+
+ .. method:: done()
+
+ Return ``True`` if the Future is *done*.
+
+ A Future is *done* if it was *cancelled* or if it has a result
+ or an exception set with :meth:`set_result` or
+ :meth:`set_exception` calls.
+
+ .. method:: add_done_callback(callback, *, context=None)
+
+ Add a callback to be run when the Future is *done*.
+
+ The *callback* is called with the Future object as its only
+ argument.
+
+ If the Future is already *done* when this method is called,
+ the callback is scheduled with :meth:`loop.call_soon`.
+
+ An optional keyword-only *context* argument allows specifying a
+ custom :class:`contextvars.Context` for the *callback* to run in.
+ The current context is used when no *context* is provided.
+
+ :func:`functools.partial` can be used to pass parameters
+ to the callback, e.g.::
+
+ # Call 'print("Future:", fut)' when "fut" is done.
+ fut.add_done_callback(
+ functools.partial(print, "Future:"))
+
+ .. versionchanged:: 3.7
+ The *context* keyword-only parameter was added.
+ See :pep:`567` for more details.
+
+ .. method:: remove_done_callback(callback)
+
+ Remove *callback* from the callbacks list.
+
+ Returns the number of callbacks removed, which is typically 1,
+ unless a callback was added more than once.
+
+ .. method:: cancel()
+
+ Cancel the Future and schedule callbacks.
+
+ If the Future is already *done* or *cancelled*, return ``False``.
+ Otherwise, change the Future's state to *cancelled*,
+ schedule the callbacks, and return ``True``.
+
+ .. method:: exception()
+
+ Return the exception that was set on this Future.
+
+ The exception (or ``None`` if no exception was set) is
+ returned only if the Future is *done*.
+
+ If the Future has been *cancelled*, this method raises a
+ :exc:`CancelledError` exception.
+
+ If the Future isn't *done* yet, this method raises an
+ :exc:`InvalidStateError` exception.
+
+ .. method:: get_loop()
+
+ Return the event loop the Future object is bound to.
+
+ .. versionadded:: 3.7
+
+ .. method:: cancelled()
+
+ Return ``True`` if the Future was *cancelled*.
+
+
+This example creates a Future object, creates and schedules an
+asynchronous Task to set result for the Future, and waits until
+the Future has a result::
+
+ async def set_after(fut, delay, value):
+ # Sleep for *delay* seconds.
+ await asyncio.sleep(delay)
+
+ # Set *value* as a result of *fut* Future.
+ fut.set_result(value)
+
+ async def main():
+ # Get the current event loop.
+ loop = asyncio.get_running_loop()
+
+ # Create a new Future object.
+ fut = loop.create_future()
+
+ # Run "set_after()" coroutine in a parallel Task.
+ # We are using the low-level "loop.create_task()" API here because
+ # we already have a reference to the event loop at hand.
+ # Otherwise we could have just used "asyncio.create_task()".
+ loop.create_task(
+ set_after(fut, 1, '... world'))
+
+ print('hello ...')
+
+ # Wait until *fut* has a result (1 second) and print it.
+ print(await fut)
+
+ asyncio.run(main())
+
+
+.. important::
+
+ The Future object was designed to mimic
+ :class:`concurrent.futures.Future`. Key differences include:
+
+ - unlike asyncio Futures, :class:`concurrent.futures.Future`
+ instances cannot be awaited.
+
+ - :meth:`asyncio.Future.result` and :meth:`asyncio.Future.exception`
+ do not accept the *timeout* argument.
+
+ - :meth:`asyncio.Future.result` and :meth:`asyncio.Future.exception`
+ raise an :exc:`InvalidStateError` exception when the Future is not
+ *done*.
+
+ - Callbacks registered with :meth:`asyncio.Future.add_done_callback`
+ are not called immediately. They are scheduled with
+ :meth:`loop.call_soon` instead.
+
+ - asyncio Future is not compatible with the
+ :func:`concurrent.futures.wait` and
+ :func:`concurrent.futures.as_completed` functions.
diff --git a/Doc/library/asyncio-protocol.rst b/Doc/library/asyncio-protocol.rst
index d7ecb25..e4aed64 100644
--- a/Doc/library/asyncio-protocol.rst
+++ b/Doc/library/asyncio-protocol.rst
@@ -1,6 +1,9 @@
.. currentmodule:: asyncio
+.. _asyncio-transports-protocols:
+
+
========================
Transports and Protocols
========================
@@ -393,11 +396,13 @@ Subprocess Transports
.. method:: SubprocessTransport.kill()
- Kill the subprocess, as in :meth:`subprocess.Popen.kill`.
+ Kill the subprocess.
On POSIX systems, the function sends SIGKILL to the subprocess.
On Windows, this method is an alias for :meth:`terminate`.
+ See also :meth:`subprocess.Popen.kill`.
+
.. method:: SubprocessTransport.send_signal(signal)
Send the *signal* number to the subprocess, as in
@@ -405,17 +410,20 @@ Subprocess Transports
.. method:: SubprocessTransport.terminate()
- Ask the subprocess to stop, as in :meth:`subprocess.Popen.terminate`.
+ Stop the subprocess.
On POSIX systems, this method sends SIGTERM to the subprocess.
On Windows, the Windows API function TerminateProcess() is called to
stop the subprocess.
+ See also :meth:`subprocess.Popen.terminate`.
+
.. method:: SubprocessTransport.close()
- Kill the subprocess by calling the :meth:`kill` method
- if the subprocess hasn't returned yet, and close transports of all
- pipes (*stdin*, *stdout* and *stderr*).
+ Kill the subprocess by calling the :meth:`kill` method.
+
+ If the subprocess hasn't returned yet, and close transports of
+ *stdin*, *stdout*, and *stderr* pipes.
.. _asyncio-protocol:
diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst
index 9f4433d..7e09b16 100644
--- a/Doc/library/asyncio-task.rst
+++ b/Doc/library/asyncio-task.rst
@@ -1,96 +1,118 @@
.. currentmodule:: asyncio
-Tasks and coroutines
+
+====================
+Coroutines and Tasks
====================
-**Source code:** :source:`Lib/asyncio/tasks.py`
+This section outlines high-level asyncio APIs to work with coroutines
+and Tasks.
+
+.. contents::
+ :depth: 1
+ :local:
-**Source code:** :source:`Lib/asyncio/coroutines.py`
.. _coroutine:
Coroutines
-----------
+==========
-Coroutines used with :mod:`asyncio` may be implemented using the
-:keyword:`async def` statement, or by using :term:`generators <generator>`.
-The :keyword:`async def` type of coroutine was added in Python 3.5, and
-is recommended if there is no need to support older Python versions.
+Coroutines declared with async/await syntax is the preferred way of
+writing asyncio applications. For example, the following snippet
+of code prints "hello", waits 1 second, and prints "world"::
-Generator-based coroutines should be decorated with :func:`@asyncio.coroutine
-<asyncio.coroutine>`, although this is not strictly enforced.
-The decorator enables compatibility with :keyword:`async def` coroutines,
-and also serves as documentation. Generator-based
-coroutines use the ``yield from`` syntax introduced in :pep:`380`,
-instead of the original ``yield`` syntax.
+ >>> import asyncio
-The word "coroutine", like the word "generator", is used for two
-different (though related) concepts:
+ >>> async def main():
+ ... print('hello')
+ ... await asyncio.sleep(1)
+ ... print('world')
-- The function that defines a coroutine
- (a function definition using :keyword:`async def` or
- decorated with ``@asyncio.coroutine``). If disambiguation is needed
- we will call this a *coroutine function* (:func:`iscoroutinefunction`
- returns ``True``).
+ >>> asyncio.run(main())
+ hello
+ world
-- The object obtained by calling a coroutine function. This object
- represents a computation or an I/O operation (usually a combination)
- that will complete eventually. If disambiguation is needed we will
- call it a *coroutine object* (:func:`iscoroutine` returns ``True``).
+Note that simply calling a coroutine will not schedule it to
+be executed::
-Things a coroutine can do:
+ >>> main()
+ <coroutine object main at 0x1053bb7c8>
-- ``result = await future`` or ``result = yield from future`` --
- suspends the coroutine until the
- future is done, then returns the future's result, or raises an
- exception, which will be propagated. (If the future is cancelled,
- it will raise a ``CancelledError`` exception.) Note that tasks are
- futures, and everything said about futures also applies to tasks.
+To actually run a coroutine asyncio provides three main mechanisms:
-- ``result = await coroutine`` or ``result = yield from coroutine`` --
- wait for another coroutine to
- produce a result (or raise an exception, which will be propagated).
- The ``coroutine`` expression must be a *call* to another coroutine.
+* By using the :func:`asyncio.run` function to run the top-level
+ entry point "main()" function (see the above example.)
-- ``return expression`` -- produce a result to the coroutine that is
- waiting for this one using :keyword:`await` or ``yield from``.
+* By awaiting on a coroutine. The following snippet of code will
+ print "hello" after waiting for 1 second, and then print "world"
+ after waiting for *another* 2 seconds::
-- ``raise exception`` -- raise an exception in the coroutine that is
- waiting for this one using :keyword:`await` or ``yield from``.
+ import asyncio
+ import time
-Calling a coroutine does not start its code running --
-the coroutine object returned by the call doesn't do anything until you
-schedule its execution. There are two basic ways to start it running:
-call ``await coroutine`` or ``yield from coroutine`` from another coroutine
-(assuming the other coroutine is already running!), or schedule its execution
-using the :func:`ensure_future` function or the :meth:`loop.create_task`
-method.
+ async def say_after(delay, what):
+ await asyncio.sleep(delay)
+ print(what)
+ async def main():
+ print('started at', time.strftime('%X'))
-Coroutines (and tasks) can only run when the event loop is running.
+ await say_after(1, 'hello')
+ await say_after(2, 'world')
-.. decorator:: coroutine
+ print('finished at', time.strftime('%X'))
- Decorator to mark generator-based coroutines. This enables
- the generator use :keyword:`!yield from` to call :keyword:`async
- def` coroutines, and also enables the generator to be called by
- :keyword:`async def` coroutines, for instance using an
- :keyword:`await` expression.
+ asyncio.run(main())
- There is no need to decorate :keyword:`async def` coroutines themselves.
+ Expected output::
- If the generator is not yielded from before it is destroyed, an error
- message is logged. See :ref:`Detect coroutines never scheduled
- <asyncio-coroutine-not-scheduled>`.
+ started at 17:13:52
+ hello
+ world
+ finished at 17:13:55
-.. note::
+* By using the :func:`asyncio.create_task` function to run coroutines
+ concurrently as asyncio :class:`Tasks <Task>`.
+
+ Let's modify the above example and run two "set_after" coroutines
+ *concurrently*::
+
+ async def main():
+ task1 = asyncio.create_task(
+ say_after(1, 'hello'))
+
+ task2 = asyncio.create_task(
+ say_after(2, 'world'))
+
+ print('started at', time.strftime('%X'))
- In this documentation, some methods are documented as coroutines,
- even if they are plain Python functions returning a :class:`Future`.
- This is intentional to have a freedom of tweaking the implementation
- of these functions in the future. If such a function is needed to be
- used in a callback-style code, wrap its result with :func:`ensure_future`.
+ # Wait until both tasks are completed (should take
+ # around 2 seconds.)
+ await task1
+ await task2
+ print('finished at', time.strftime('%X'))
+
+ Note that expected output now shows that the snippet runs
+ 1 second faster than before::
+
+ started at 17:14:32
+ hello
+ world
+ finished at 17:14:34
+
+Note that in this documentation the term "coroutine" can be used for
+two closely related concepts:
+
+* a *coroutine function*: an :keyword:`async def` function;
+
+* a *coroutine object*: object returned by calling a
+ *coroutine function*.
+
+
+Running an asyncio Program
+==========================
.. function:: run(coro, \*, debug=False)
@@ -101,7 +123,7 @@ Coroutines (and tasks) can only run when the event loop is running.
This function cannot be called when another asyncio event loop is
running in the same thread.
- If debug is True, the event loop will be run in debug mode.
+ If *debug* is ``True``, the event loop will be run in debug mode.
This function always creates a new event loop and closes it at
the end. It should be used as a main entry point for asyncio
@@ -112,34 +134,41 @@ Coroutines (and tasks) can only run when the event loop is running.
on a :term:`provisional basis <provisional api>`.
-.. _asyncio-hello-world-coroutine:
+Creating Tasks
+==============
-Example: Hello World coroutine
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. function:: create_task(coro, \*, name=None)
-Example of coroutine displaying ``"Hello World"``::
+ Wrap a :ref:`coroutine <coroutine>` *coro* into a task and schedule
+ its execution. Return the task object.
- import asyncio
+ If *name* is not ``None``, it is set as the name of the task using
+ :meth:`Task.set_name`.
+
+ The task is executed in :func:`get_running_loop` context,
+ :exc:`RuntimeError` is raised if there is no running loop in
+ current thread.
+
+ .. versionadded:: 3.7
- async def hello_world():
- print("Hello World!")
+ .. versionchanged:: 3.8
+ Added the ``name`` parameter.
- asyncio.run(hello_world())
-.. seealso::
+Sleeping
+========
- The :ref:`Hello World with call_soon() <asyncio-hello-world-callback>`
- example uses the :meth:`loop.call_soon` method to schedule a
- callback.
+.. coroutinefunction:: sleep(delay, result=None, \*, loop=None)
+ Block for *delay* seconds.
-.. _asyncio-date-coroutine:
+ If *result* is provided, it is returned to the caller
+ when the coroutine completes.
-Example: Coroutine displaying the current date
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ .. _asyncio-date-coroutine:
-Example of coroutine displaying the current date every second during 5 seconds
-using the :meth:`sleep` function::
+ Example of coroutine displaying the current date every second
+ during 5 seconds::
import asyncio
import datetime
@@ -155,418 +184,279 @@ using the :meth:`sleep` function::
asyncio.run(display_date())
-.. seealso::
-
- The :ref:`display the current date with call_later()
- <asyncio-date-callback>` example uses a callback with the
- :meth:`loop.call_later` method.
-
-
-Example: Chain coroutines
-^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Example chaining coroutines::
-
- import asyncio
-
- async def compute(x, y):
- print("Compute %s + %s ..." % (x, y))
- await asyncio.sleep(1.0)
- return x + y
-
- async def print_sum(x, y):
- result = await compute(x, y)
- print("%s + %s = %s" % (x, y, result))
-
- loop = asyncio.get_event_loop()
- loop.run_until_complete(print_sum(1, 2))
- loop.close()
-
-``compute()`` is chained to ``print_sum()``: ``print_sum()`` coroutine waits
-until ``compute()`` is completed before returning its result.
-
-Sequence diagram of the example:
-
-.. image:: tulip_coro.png
- :align: center
-
-The "Task" is created by the :meth:`loop.run_until_complete` method
-when it gets a coroutine object instead of a task.
-
-The diagram shows the control flow, it does not describe exactly how things
-work internally. For example, the sleep coroutine creates an internal future
-which uses :meth:`loop.call_later` to wake up the task in 1 second.
-
-
-Future
-------
-
-.. class:: Future(\*, loop=None)
-
- This class is *almost* compatible with :class:`concurrent.futures.Future`.
-
- Differences:
-
- - :meth:`result` and :meth:`exception` do not take a timeout argument and
- raise an exception when the future isn't done yet.
-
- - Callbacks registered with :meth:`add_done_callback` are always called
- via the event loop's :meth:`loop.call_soon`.
-
- - This class is not compatible with the :func:`~concurrent.futures.wait` and
- :func:`~concurrent.futures.as_completed` functions in the
- :mod:`concurrent.futures` package.
-
- This class is :ref:`not thread safe <asyncio-multithreading>`.
-
- .. method:: cancel()
-
- Cancel the future and schedule callbacks.
-
- If the future is already done or cancelled, return ``False``. Otherwise,
- change the future's state to cancelled, schedule the callbacks and return
- ``True``.
-
- .. method:: cancelled()
-
- Return ``True`` if the future was cancelled.
-
- .. method:: done()
-
- Return ``True`` if the future is done.
-
- Done means either that a result / exception are available, or that the
- future was cancelled.
- .. method:: result()
+Running Tasks Concurrently
+==========================
- Return the result this future represents.
+.. coroutinefunction:: gather(\*fs, loop=None, return_exceptions=False)
- If the future has been cancelled, raises :exc:`CancelledError`. If the
- future's result isn't yet available, raises :exc:`InvalidStateError`. If
- the future is done and has an exception set, this exception is raised.
+ Return a Future aggregating results from the given coroutine objects,
+ Tasks, or Futures.
- .. method:: exception()
+ If all Tasks/Futures are completed successfully, the result is an
+ aggregate list of returned values. The result values are in the
+ order of the original *fs* sequence.
- Return the exception that was set on this future.
+ All coroutines in the *fs* list are automatically
+ wrapped in :class:`Tasks <Task>`.
- The exception (or ``None`` if no exception was set) is returned only if
- the future is done. If the future has been cancelled, raises
- :exc:`CancelledError`. If the future isn't done yet, raises
- :exc:`InvalidStateError`.
+ If *return_exceptions* is ``True``, exceptions in the Tasks/Futures
+ are treated the same as successful results, and gathered in the
+ result list. Otherwise, the first raised exception is immediately
+ propagated to the returned Future.
- .. method:: add_done_callback(callback, *, context=None)
+ If the outer Future is *cancelled*, all submitted Tasks/Futures
+ (that have not completed yet) are also *cancelled*.
- Add a callback to be run when the future becomes done.
+ If any child is *cancelled*, it is treated as if it raised
+ :exc:`CancelledError` -- the outer Future is **not** cancelled in
+ this case. This is to prevent the cancellation of one submitted
+ Task/Future to cause other Tasks/Futures to be cancelled.
- The *callback* is called with a single argument - the future object. If the
- future is already done when this is called, the callback is scheduled
- with :meth:`loop.call_soon`.
+ All futures must share the same event loop.
- An optional keyword-only *context* argument allows specifying a custom
- :class:`contextvars.Context` for the *callback* to run in. The current
- context is used when no *context* is provided.
-
- :ref:`Use functools.partial to pass parameters to the callback
- <asyncio-pass-keywords>`. For example,
- ``fut.add_done_callback(functools.partial(print, "Future:",
- flush=True))`` will call ``print("Future:", fut, flush=True)``.
-
- .. versionchanged:: 3.7
- The *context* keyword-only parameter was added. See :pep:`567`
- for more details.
-
- .. method:: remove_done_callback(fn)
-
- Remove all instances of a callback from the "call when done" list.
-
- Returns the number of callbacks removed.
-
- .. method:: set_result(result)
-
- Mark the future done and set its result.
-
- If the future is already done when this method is called, raises
- :exc:`InvalidStateError`.
-
- .. method:: set_exception(exception)
-
- Mark the future done and set an exception.
-
- If the future is already done when this method is called, raises
- :exc:`InvalidStateError`.
-
- .. method:: get_loop()
-
- Return the event loop the future object is bound to.
+ .. versionchanged:: 3.7
+ If the *gather* itself is cancelled, the cancellation is
+ propagated regardless of *return_exceptions*.
- .. versionadded:: 3.7
+ Example::
+ import asyncio
-Example: Future with run_until_complete()
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ async def factorial(name, number):
+ f = 1
+ for i in range(2, number + 1):
+ print(f"Task {name}: Compute factorial({i})...")
+ await asyncio.sleep(1)
+ f *= i
+ print(f"Task {name}: factorial({number}) = {f}")
-Example combining a :class:`Future` and a :ref:`coroutine function
-<coroutine>`::
+ async def main():
+ await asyncio.gather(
+ factorial("A", 2),
+ factorial("B", 3),
+ factorial("C", 4),
+ ))
- import asyncio
+ asyncio.run(main())
- async def slow_operation(future):
- await asyncio.sleep(1)
- future.set_result('Future is done!')
+ # Expected output:
+ #
+ # Task A: Compute factorial(2)...
+ # Task B: Compute factorial(2)...
+ # Task C: Compute factorial(2)...
+ # Task A: factorial(2) = 2
+ # Task B: Compute factorial(3)...
+ # Task C: Compute factorial(3)...
+ # Task B: factorial(3) = 6
+ # Task C: Compute factorial(4)...
+ # Task C: factorial(4) = 24
- loop = asyncio.get_event_loop()
- future = asyncio.Future()
- asyncio.ensure_future(slow_operation(future))
- loop.run_until_complete(future)
- print(future.result())
- loop.close()
-The coroutine function is responsible for the computation (which takes 1 second)
-and it stores the result into the future. The
-:meth:`loop.run_until_complete` method waits for the completion of
-the future.
+Shielding Tasks From Cancellation
+=================================
-.. note::
- The :meth:`loop.run_until_complete` method uses internally the
- :meth:`~Future.add_done_callback` method to be notified when the future is
- done.
+.. coroutinefunction:: shield(fut, \*, loop=None)
+ Wait for a Future/Task while protecting it from being cancelled.
-Example: Future with run_forever()
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ *fut* can be a coroutine, a Task, or a Future-like object. If
+ *fut* is a coroutine it is automatically wrapped in a
+ :class:`Task`.
-The previous example can be written differently using the
-:meth:`Future.add_done_callback` method to describe explicitly the control
-flow::
+ The statement::
- import asyncio
+ res = await shield(something())
- async def slow_operation(future):
- await asyncio.sleep(1)
- future.set_result('Future is done!')
+ is equivalent to the statement::
- def got_result(future):
- print(future.result())
- loop.stop()
+ res = await something()
- loop = asyncio.get_event_loop()
- future = asyncio.Future()
- asyncio.ensure_future(slow_operation(future))
- future.add_done_callback(got_result)
- try:
- loop.run_forever()
- finally:
- loop.close()
+ *except* that if the coroutine containing it is cancelled, the
+ Task running in ``something()`` is not cancelled. From the point
+ of view of ``something()``, the cancellation did not happen.
+ Although its caller is still cancelled, so the "await" expression
+ still raises :exc:`CancelledError`.
-In this example, the future is used to link ``slow_operation()`` to
-``got_result()``: when ``slow_operation()`` is done, ``got_result()`` is called
-with the result.
+ If ``something()`` is cancelled by other means (i.e. from within
+ itself) that would also cancel ``shield()``.
+ If it is desired to completely ignore cancellation (not recommended)
+ the ``shield()`` function should be combined with a try/except
+ clause, as follows::
-Task
-----
+ try:
+ res = await shield(something())
+ except CancelledError:
+ res = None
-.. function:: create_task(coro, \*, name=None)
- Wrap a :ref:`coroutine <coroutine>` *coro* into a task and schedule
- its execution. Return the task object.
+Timeouts
+========
- If *name* is not ``None``, it is set as the name of the task using
- :meth:`Task.set_name`.
+.. coroutinefunction:: wait_for(fut, timeout, \*, loop=None)
- The task is executed in :func:`get_running_loop` context,
- :exc:`RuntimeError` is raised if there is no running loop in
- current thread.
+ Wait for the coroutine, Task, or Future to complete with timeout.
- .. versionadded:: 3.7
+ *fut* can be a coroutine, a Task, or a Future-like object. If
+ *fut* is a coroutine it is automatically wrapped in a
+ :class:`Task`.
- .. versionchanged:: 3.8
- Added the ``name`` parameter.
+ *timeout* can either be ``None`` or a float or int number of seconds
+ to wait for. If *timeout* is ``None``, block until the future
+ completes.
-.. class:: Task(coro, \*, loop=None, name=None)
+ If a timeout occurs, it cancels the task and raises
+ :exc:`asyncio.TimeoutError`.
- A unit for concurrent running of :ref:`coroutines <coroutine>`,
- subclass of :class:`Future`.
+ To avoid the task cancellation, wrap it in :func:`shield`.
- A task is responsible for executing a coroutine object in an event loop. If
- the wrapped coroutine yields from a future, the task suspends the execution
- of the wrapped coroutine and waits for the completion of the future. When
- the future is done, the execution of the wrapped coroutine restarts with the
- result or the exception of the future.
+ The function will wait until the future is actually cancelled,
+ so the total wait time may exceed the *timeout*.
- Event loops use cooperative scheduling: an event loop only runs one task at
- a time. Other tasks may run in parallel if other event loops are
- running in different threads. While a task waits for the completion of a
- future, the event loop executes a new task.
+ If the wait is cancelled, the future *fut* is also cancelled.
- The cancellation of a task is different from the cancellation of a
- future. Calling :meth:`cancel` will throw a
- :exc:`~concurrent.futures.CancelledError` to the wrapped
- coroutine. :meth:`~Future.cancelled` only returns ``True`` if the
- wrapped coroutine did not catch the
- :exc:`~concurrent.futures.CancelledError` exception, or raised a
- :exc:`~concurrent.futures.CancelledError` exception.
+ Example::
- If a pending task is destroyed, the execution of its wrapped :ref:`coroutine
- <coroutine>` did not complete. It is probably a bug and a warning is
- logged: see :ref:`Pending task destroyed <asyncio-pending-task-destroyed>`.
+ async def eternity():
+ # Sleep for one hour
+ await asyncio.sleep(3600)
+ print('yay!')
- Don't directly create :class:`Task` instances: use the :func:`create_task`
- function or the :meth:`loop.create_task` method.
+ async def main():
+ # Wait for at most 1 second
+ try:
+ await asyncio.wait_for(eternity(), timeout=1.0)
+ except asyncio.TimeoutError:
+ print('timeout!')
- Tasks support the :mod:`contextvars` module. When a Task
- is created it copies the current context and later runs its coroutine
- in the copied context. See :pep:`567` for more details.
+ asyncio.run(main())
- This class is :ref:`not thread safe <asyncio-multithreading>`.
+ # Expected output:
+ #
+ # timeout!
.. versionchanged:: 3.7
- Added support for the :mod:`contextvars` module.
-
- .. versionchanged:: 3.8
- Added the ``name`` parameter.
+ When *fut* is cancelled due to a timeout, ``wait_for`` waits
+ for *fut* to be cancelled. Previously, it raised
+ :exc:`asyncio.TimeoutError` immediately.
- .. classmethod:: all_tasks(loop=None)
- Return a set of all tasks for an event loop.
+Waiting Primitives
+==================
- By default all tasks for the current event loop are returned.
- If *loop* is ``None``, :func:`get_event_loop` function
- is used to get the current loop.
-
- .. classmethod:: current_task(loop=None)
-
- Return the currently running task in an event loop or ``None``.
-
- By default the current task for the current event loop is returned.
-
- ``None`` is returned when called not in the context of a :class:`Task`.
-
- .. method:: cancel()
-
- Request that this task cancel itself.
-
- This arranges for a :exc:`~concurrent.futures.CancelledError` to be
- thrown into the wrapped coroutine on the next cycle through the event
- loop. The coroutine then has a chance to clean up or even deny the
- request using try/except/finally.
+.. coroutinefunction:: wait(fs, \*, loop=None, timeout=None,\
+ return_when=ALL_COMPLETED)
- Unlike :meth:`Future.cancel`, this does not guarantee that the task
- will be cancelled: the exception might be caught and acted upon, delaying
- cancellation of the task or preventing cancellation completely. The task
- may also return a value or raise a different exception.
+ Wait for a set of Futures to complete.
- Immediately after this method is called, :meth:`~Future.cancelled` will
- not return ``True`` (unless the task was already cancelled). A task will
- be marked as cancelled when the wrapped coroutine terminates with a
- :exc:`~concurrent.futures.CancelledError` exception (even if
- :meth:`cancel` was not called).
+ *fs* is a list of coroutines, Futures, and/or Tasks. Coroutines
+ are automatically wrapped in :class:`Tasks <Task>`.
- .. method:: get_stack(\*, limit=None)
+ Returns two sets of Tasks/Futures: ``(done, pending)``.
- Return the list of stack frames for this task's coroutine.
+ *timeout* (a float or int), if specified, can be used to control
+ the maximum number of seconds to wait before returning.
- If the coroutine is not done, this returns the stack where it is
- suspended. If the coroutine has completed successfully or was
- cancelled, this returns an empty list. If the coroutine was
- terminated by an exception, this returns the list of traceback
- frames.
+ Note that this function does not raise :exc:`asyncio.TimeoutError`.
+ Futures or Tasks that aren't done when the timeout occurs are just
+ returned in the second set.
- The frames are always ordered from oldest to newest.
+ *return_when* indicates when this function should return. It must
+ be one of the following constants:
- The optional limit gives the maximum number of frames to return; by
- default all available frames are returned. Its meaning differs depending
- on whether a stack or a traceback is returned: the newest frames of a
- stack are returned, but the oldest frames of a traceback are returned.
- (This matches the behavior of the traceback module.)
+ .. tabularcolumns:: |l|L|
- For reasons beyond our control, only one stack frame is returned for a
- suspended coroutine.
+ +-----------------------------+----------------------------------------+
+ | Constant | Description |
+ +=============================+========================================+
+ | :const:`FIRST_COMPLETED` | The function will return when any |
+ | | future finishes or is cancelled. |
+ +-----------------------------+----------------------------------------+
+ | :const:`FIRST_EXCEPTION` | The function will return when any |
+ | | future finishes by raising an |
+ | | exception. If no future raises an |
+ | | exception then it is equivalent to |
+ | | :const:`ALL_COMPLETED`. |
+ +-----------------------------+----------------------------------------+
+ | :const:`ALL_COMPLETED` | The function will return when all |
+ | | futures finish or are cancelled. |
+ +-----------------------------+----------------------------------------+
- .. method:: print_stack(\*, limit=None, file=None)
+ Unlike :func:`~asyncio.wait_for`, ``wait()`` does not cancel the
+ futures when a timeout occurs.
- Print the stack or traceback for this task's coroutine.
+ Usage::
- This produces output similar to that of the traceback module, for the
- frames retrieved by get_stack(). The limit argument is passed to
- get_stack(). The file argument is an I/O stream to which the output
- is written; by default output is written to sys.stderr.
+ done, pending = await asyncio.wait(fs)
- .. method:: get_name()
- Return the name of the task.
+.. function:: as_completed(fs, \*, loop=None, timeout=None)
- If no name has been explicitly assigned to the task, the default
- ``Task`` implementation generates a default name during instantiation.
+ Return an iterator which values, when waited for, are
+ :class:`Future` instances.
- .. versionadded:: 3.8
+ Raises :exc:`asyncio.TimeoutError` if the timeout occurs before
+ all Futures are done.
- .. method:: set_name(value)
+ Example::
- Set the name of the task.
+ for f in as_completed(fs):
+ result = await f
+ # ...
- The *value* argument can be any object, which is then converted to a
- string.
- In the default ``Task`` implementation, the name will be visible in the
- :func:`repr` output of a task object.
+Scheduling From Other Threads
+=============================
- .. versionadded:: 3.8
+.. function:: run_coroutine_threadsafe(coro, loop)
+ Submit a coroutine to the given event loop. Thread-safe.
-Example: Parallel execution of tasks
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ Return a :class:`concurrent.futures.Future` to access the result.
-Example executing 3 tasks (A, B, C) in parallel::
+ This function is meant to be called from a different OS thread
+ than the one where the event loop is running. Example::
- import asyncio
+ # Create a coroutine
+ coro = asyncio.sleep(1, result=3)
- async def factorial(name, number):
- f = 1
- for i in range(2, number+1):
- print("Task %s: Compute factorial(%s)..." % (name, i))
- await asyncio.sleep(1)
- f *= i
- print("Task %s: factorial(%s) = %s" % (name, number, f))
+ # Submit the coroutine to a given loop
+ future = asyncio.run_coroutine_threadsafe(coro, loop)
- loop = asyncio.get_event_loop()
- loop.run_until_complete(asyncio.gather(
- factorial("A", 2),
- factorial("B", 3),
- factorial("C", 4),
- ))
- loop.close()
+ # Wait for the result with an optional timeout argument
+ assert future.result(timeout) == 3
-Output::
+ If an exception is raised in the coroutine, the returned Future
+ will be notified. It can also be used to cancel the task in
+ the event loop::
- Task A: Compute factorial(2)...
- Task B: Compute factorial(2)...
- Task C: Compute factorial(2)...
- Task A: factorial(2) = 2
- Task B: Compute factorial(3)...
- Task C: Compute factorial(3)...
- Task B: factorial(3) = 6
- Task C: Compute factorial(4)...
- Task C: factorial(4) = 24
+ try:
+ result = future.result(timeout)
+ except asyncio.TimeoutError:
+ print('The coroutine took too long, cancelling the task...')
+ future.cancel()
+ except Exception as exc:
+ print('The coroutine raised an exception: {!r}'.format(exc))
+ else:
+ print('The coroutine returned: {!r}'.format(result))
-A task is automatically scheduled for execution when it is created. The event
-loop stops when all tasks are done.
+ See the :ref:`concurrency and multithreading <asyncio-multithreading>`
+ section of the documentation.
+ Unlike other asyncio functions this functions requires the *loop*
+ argument to be passed explicitly.
-Task functions
---------------
+ .. versionadded:: 3.5.1
-.. note::
- In the functions below, the optional *loop* argument allows explicitly setting
- the event loop object used by the underlying task or coroutine. If it's
- not provided, the default event loop is used.
+Introspection
+=============
.. function:: current_task(loop=None)
- Return the current running :class:`Task` instance or ``None``, if
+ Return the currently running :class:`Task` instance, or ``None`` if
no task is running.
If *loop* is ``None`` :func:`get_running_loop` is used to get
@@ -577,246 +467,259 @@ Task functions
.. function:: all_tasks(loop=None)
- Return a set of :class:`Task` objects created for the loop.
+ Return a set of not yet finished :class:`Task` objects run by
+ the loop.
If *loop* is ``None``, :func:`get_running_loop` is used for getting
- current loop (contrary to the deprecated :meth:`Task.all_tasks` method
- that uses :func:`get_event_loop`.)
+ current loop.
.. versionadded:: 3.7
-.. function:: as_completed(fs, \*, loop=None, timeout=None)
+Task Object
+===========
- Return an iterator whose values, when waited for, are :class:`Future`
- instances.
+.. class:: Task(coro, \*, loop=None, name=None)
- Raises :exc:`asyncio.TimeoutError` if the timeout occurs before all Futures
- are done.
+ A :class:`Future`-like object that wraps a Python
+ :ref:`coroutine <coroutine>`. Not thread-safe.
- Example::
+ Tasks are used to run coroutines in event loops.
+ If a coroutine awaits on a Future, the Task suspends
+ the execution of the coroutine and waits for the completion
+ of the Future. When the Future is *done*, the execution of
+ the wrapped coroutine resumes.
- for f in as_completed(fs):
- result = await f # The 'await' may raise
- # Use result
+ Event loops use cooperative scheduling: an event loop runs
+ one Task at a time. While a Task awaits for the completion of a
+ Future, the event loop runs other Tasks, callbacks, or performs
+ IO operations.
- .. note::
+ Use the high-level :func:`asyncio.create_task` function to create
+ Tasks, or low-level :meth:`loop.create_task` or
+ :func:`ensure_future` functions. Manually instantiating Task
+ objects is discouraged.
- The futures ``f`` are not necessarily members of fs.
+ To cancel a running Task use the :meth:`cancel` method. Calling it
+ will cause the Task to throw a :exc:`CancelledError` exception into
+ the wrapped coroutine. If a coroutine is awaiting on a Future
+ object during cancellation, the Future object will be cancelled.
-.. function:: ensure_future(coro_or_future, \*, loop=None)
+ :meth:`cancelled` can be used to check if the Task was cancelled.
+ The method returns ``True`` if the wrapped coroutine did not
+ suppress the :exc:`CancelledError` exception and was actually
+ cancelled.
- Schedule the execution of a :ref:`coroutine object <coroutine>`: wrap it in
- a future. Return a :class:`Task` object.
+ :class:`asyncio.Task` inherits from :class:`Future` all of its
+ APIs except :meth:`Future.set_result` and
+ :meth:`Future.set_exception`.
- If the argument is a :class:`Future`, it is returned directly.
+ Tasks support the :mod:`contextvars` module. When a Task
+ is created it copies the current context and later runs its
+ coroutine in the copied context.
- .. versionadded:: 3.4.4
+ .. versionchanged:: 3.7
+ Added support for the :mod:`contextvars` module.
- .. versionchanged:: 3.5.1
- The function accepts any :term:`awaitable` object.
+ .. versionchanged:: 3.8
+ Added the ``name`` parameter.
- .. note::
+ .. method:: cancel()
- :func:`create_task` (added in Python 3.7) is the preferable way
- for spawning new tasks.
+ Request the Task to be cancelled.
- .. seealso::
+ This arranges for a :exc:`CancelledError` exception to be thrown
+ into the wrapped coroutine on the next cycle of the event loop.
- The :func:`create_task` function and
- :meth:`loop.create_task` method.
+ The coroutine then has a chance to clean up or even deny the
+ request by suppressing the exception with a :keyword:`try` ...
+ ... ``except CancelledError`` ... :keyword:`finally` block.
+ Therefore, unlike :meth:`Future.cancel`, :meth:`Task.cancel` does
+ not guarantee that the Task will be cancelled, although
+ suppressing cancellation completely is not common and is actively
+ discouraged.
-.. function:: wrap_future(future, \*, loop=None)
+ The following example illustrates how coroutines can intercept
+ the cancellation request::
- Wrap a :class:`concurrent.futures.Future` object in a :class:`Future`
- object.
+ async def cancel_me():
+ print('cancel_me(): before sleep')
-.. function:: gather(\*coros_or_futures, loop=None, return_exceptions=False)
+ try:
+ # Wait for 1 hour
+ await asyncio.sleep(3600)
+ except asyncio.CancelledError:
+ print('cancel_me(): cancel sleep')
+ raise
+ finally:
+ print('cancel_me(): after sleep')
- Return a future aggregating results from the given coroutine objects or
- futures.
+ async def main():
+ # Create a "cancel_me" Task
+ task = asyncio.create_task(cancel_me())
- All futures must share the same event loop. If all the tasks are done
- successfully, the returned future's result is the list of results (in the
- order of the original sequence, not necessarily the order of results
- arrival). If *return_exceptions* is true, exceptions in the tasks are
- treated the same as successful results, and gathered in the result list;
- otherwise, the first raised exception will be immediately propagated to the
- returned future.
+ # Wait for 1 second
+ await asyncio.sleep(1)
- Cancellation: if the outer Future is cancelled, all children (that have not
- completed yet) are also cancelled. If any child is cancelled, this is
- treated as if it raised :exc:`~concurrent.futures.CancelledError` -- the
- outer Future is *not* cancelled in this case. (This is to prevent the
- cancellation of one child to cause other children to be cancelled.)
+ task.cancel()
+ try:
+ await task
+ except asyncio.CancelledError:
+ print("main(): cancel_me is cancelled now")
- .. versionchanged:: 3.7.0
- If the *gather* itself is cancelled, the cancellation is propagated
- regardless of *return_exceptions*.
+ asyncio.run(main())
-.. function:: iscoroutine(obj)
+ # Expected output:
+ #
+ # cancel_me(): before sleep
+ # cancel_me(): cancel sleep
+ # cancel_me(): after sleep
+ # main(): cancel_me is cancelled now
- Return ``True`` if *obj* is a :ref:`coroutine object <coroutine>`,
- which may be based on a generator or an :keyword:`async def` coroutine.
+ .. method:: cancelled()
-.. function:: iscoroutinefunction(func)
+ Return ``True`` if the Task is *cancelled*.
- Return ``True`` if *func* is determined to be a :ref:`coroutine function
- <coroutine>`, which may be a decorated generator function or an
- :keyword:`async def` function.
+ The Task is *cancelled* when the cancellation was requested with
+ :meth:`cancel` and the wrapped coroutine propagated the
+ :exc:`CancelledError` exception thrown into it.
-.. function:: run_coroutine_threadsafe(coro, loop)
+ .. method:: done()
- Submit a :ref:`coroutine object <coroutine>` to a given event loop.
+ Return ``True`` if the Task is *done*.
- Return a :class:`concurrent.futures.Future` to access the result.
+ A Task is *done* when the wrapped coroutine either returned
+ a value, raised an exception, or the Task was cancelled.
- This function is meant to be called from a different thread than the one
- where the event loop is running. Usage::
+ .. method:: get_stack(\*, limit=None)
- # Create a coroutine
- coro = asyncio.sleep(1, result=3)
- # Submit the coroutine to a given loop
- future = asyncio.run_coroutine_threadsafe(coro, loop)
- # Wait for the result with an optional timeout argument
- assert future.result(timeout) == 3
+ Return the list of stack frames for this Task.
- If an exception is raised in the coroutine, the returned future will be
- notified. It can also be used to cancel the task in the event loop::
+ If the wrapped coroutine is not done, this returns the stack
+ where it is suspended. If the coroutine has completed
+ successfully or was cancelled, this returns an empty list.
+ If the coroutine was terminated by an exception, this returns
+ the list of traceback frames.
- try:
- result = future.result(timeout)
- except asyncio.TimeoutError:
- print('The coroutine took too long, cancelling the task...')
- future.cancel()
- except Exception as exc:
- print('The coroutine raised an exception: {!r}'.format(exc))
- else:
- print('The coroutine returned: {!r}'.format(result))
+ The frames are always ordered from oldest to newest.
- See the :ref:`concurrency and multithreading <asyncio-multithreading>`
- section of the documentation.
+ Only one stack frame is returned for a suspended coroutine.
- .. note::
+ The optional *limit* argument sets the maximum number of frames
+ to return; by default all available frames are returned.
+ The ordering of the returned list differs depending on whether
+ a stack or a traceback is returned: the newest frames of a
+ stack are returned, but the oldest frames of a traceback are
+ returned. (This matches the behavior of the traceback module.)
- Unlike other functions from the module,
- :func:`run_coroutine_threadsafe` requires the *loop* argument to
- be passed explicitly.
+ .. method:: print_stack(\*, limit=None, file=None)
- .. versionadded:: 3.5.1
+ Print the stack or traceback for this Task.
-.. coroutinefunction:: sleep(delay, result=None, \*, loop=None)
+ This produces output similar to that of the traceback module
+ for the frames retrieved by :meth:`get_stack`.
- Create a :ref:`coroutine <coroutine>` that completes after a given
- time (in seconds). If *result* is provided, it is produced to the caller
- when the coroutine completes.
+ The *limit* argument is passed to :meth:`get_stack` directly.
- The resolution of the sleep depends on the :ref:`granularity of the event
- loop <asyncio-delayed-calls>`.
+ The *file* argument is an I/O stream to which the output
+ is written; by default output is written to :data:`sys.stderr`.
- This function is a :ref:`coroutine <coroutine>`.
+ .. method:: get_name()
-.. coroutinefunction:: shield(arg, \*, loop=None)
+ Return the name of the Task.
- Wait for a future, shielding it from cancellation.
+ If no name has been explicitly assigned to the Task, the default
+ asyncio Task implementation generates a default name during
+ instantiation.
- The statement::
+ .. versionadded:: 3.8
- res = await shield(something())
+ .. method:: set_name(value)
- is exactly equivalent to the statement::
+ Set the name of the Task.
- res = await something()
+ The *value* argument can be any object, which is then
+ converted to a string.
- *except* that if the coroutine containing it is cancelled, the task running
- in ``something()`` is not cancelled. From the point of view of
- ``something()``, the cancellation did not happen. But its caller is still
- cancelled, so the yield-from expression still raises
- :exc:`~concurrent.futures.CancelledError`. Note: If ``something()`` is
- cancelled by other means this will still cancel ``shield()``.
+ In the default Task implementation, the name will be visible
+ in the :func:`repr` output of a task object.
- If you want to completely ignore cancellation (not recommended) you can
- combine ``shield()`` with a try/except clause, as follows::
+ .. versionadded:: 3.8
- try:
- res = await shield(something())
- except CancelledError:
- res = None
+ .. classmethod:: all_tasks(loop=None)
+ Return a set of all tasks for an event loop.
-.. coroutinefunction:: wait(futures, \*, loop=None, timeout=None,\
- return_when=ALL_COMPLETED)
+ By default all tasks for the current event loop are returned.
+ If *loop* is ``None``, the :func:`get_event_loop` function
+ is used to get the current loop.
- Wait for the Futures and coroutine objects given by the sequence *futures*
- to complete. Coroutines will be wrapped in Tasks. Returns two sets of
- :class:`Future`: (done, pending).
+ This function is **deprecated** and scheduled for removal in
+ Python 3.9. Use the :func:`all_tasks` function instead.
- The sequence *futures* must not be empty.
+ .. classmethod:: current_task(loop=None)
- *timeout* can be used to control the maximum number of seconds to wait before
- returning. *timeout* can be an int or float. If *timeout* is not specified
- or ``None``, there is no limit to the wait time.
+ Return the currently running task or ``None``.
- *return_when* indicates when this function should return. It must be one of
- the following constants of the :mod:`concurrent.futures` module:
+ If *loop* is ``None``, the :func:`get_event_loop` function
+ is used to get the current loop.
- .. tabularcolumns:: |l|L|
+ This function is **deprecated** and scheduled for removal in
+ Python 3.9. Use the :func:`current_task` function instead.
- +-----------------------------+----------------------------------------+
- | Constant | Description |
- +=============================+========================================+
- | :const:`FIRST_COMPLETED` | The function will return when any |
- | | future finishes or is cancelled. |
- +-----------------------------+----------------------------------------+
- | :const:`FIRST_EXCEPTION` | The function will return when any |
- | | future finishes by raising an |
- | | exception. If no future raises an |
- | | exception then it is equivalent to |
- | | :const:`ALL_COMPLETED`. |
- +-----------------------------+----------------------------------------+
- | :const:`ALL_COMPLETED` | The function will return when all |
- | | futures finish or are cancelled. |
- +-----------------------------+----------------------------------------+
- Unlike :func:`~asyncio.wait_for`, ``wait()`` will not cancel the futures
- when a timeout occurs.
+.. _asyncio_generator_based_coro:
- This function is a :ref:`coroutine <coroutine>`.
+Generator-based Coroutines
+==========================
- Usage::
+.. note::
- done, pending = await asyncio.wait(fs)
+ Support for generator-based coroutines is **deprecated** and
+ scheduled for removal in Python 4.0.
- .. note::
+Generator-based coroutines predate async/await syntax. They are
+Python generators that use ``yield from`` expression is to await
+on Futures and other coroutines.
- This does not raise :exc:`asyncio.TimeoutError`! Futures that aren't done
- when the timeout occurs are returned in the second set.
+Generator-based coroutines should be decorated with
+:func:`@asyncio.coroutine <asyncio.coroutine>`, although this is not
+enforced.
-.. coroutinefunction:: wait_for(fut, timeout, \*, loop=None)
+.. decorator:: coroutine
- Wait for the single :class:`Future` or :ref:`coroutine object <coroutine>`
- to complete with timeout. If *timeout* is ``None``, block until the future
- completes.
+ Decorator to mark generator-based coroutines.
- Coroutine will be wrapped in :class:`Task`.
+ This decorator enables legacy generator-based coroutines to be
+ compatible with async/await code::
- Returns result of the Future or coroutine. When a timeout occurs, it
- cancels the task and raises :exc:`asyncio.TimeoutError`. To avoid the task
- cancellation, wrap it in :func:`shield`. The function will wait until
- the future is actually cancelled, so the total wait time may exceed
- the *timeout*.
+ @asyncio.coroutine
+ def old_style_coroutine():
+ yield from asyncio.sleep(1)
- If the wait is cancelled, the future *fut* is also cancelled.
+ async def main():
+ await old_style_coroutine()
+
+ This decorator is **deprecated** and is scheduled for removal in
+ Python 4.0.
- This function is a :ref:`coroutine <coroutine>`, usage::
+ This decorator should not be used for :keyword:`async def`
+ coroutines.
- result = await asyncio.wait_for(fut, 60.0)
+.. function:: iscoroutine(obj)
- .. versionchanged:: 3.4.3
- If the wait is cancelled, the future *fut* is now also cancelled.
+ Return ``True`` if *obj* is a :ref:`coroutine object <coroutine>`.
- .. versionchanged:: 3.7
- When *fut* is cancelled due to a timeout, ``wait_for`` now waits
- for *fut* to be cancelled. Previously,
- it raised :exc:`~asyncio.TimeoutError` immediately.
+ This method is different from :func:`inspect.iscoroutine` because
+ it returns ``True`` for generator-based coroutines decorated with
+ :func:`@coroutine <coroutine>`.
+
+.. function:: iscoroutinefunction(func)
+
+ Return ``True`` if *func* is a :ref:`coroutine function
+ <coroutine>`.
+
+ This method is different from :func:`inspect.iscoroutinefunction`
+ because it returns ``True`` for generator-based coroutine functions
+ decorated with :func:`@coroutine <coroutine>`.
diff --git a/Doc/library/asyncio.rst b/Doc/library/asyncio.rst
index 0d58a94..2c8ccbb 100644
--- a/Doc/library/asyncio.rst
+++ b/Doc/library/asyncio.rst
@@ -1,15 +1,13 @@
-:mod:`asyncio` --- Asynchronous I/O, event loop, coroutines and tasks
-=====================================================================
+:mod:`asyncio` --- Asynchronous I/O
+===================================
.. module:: asyncio
- :synopsis: Asynchronous I/O, event loop, coroutines and tasks.
-
-.. versionadded:: 3.4
-
-**Source code:** :source:`Lib/asyncio/`
+ :synopsis: Asynchronous I/O.
--------------
+.. TODO: rewrite the introduction section
+
This module provides infrastructure for writing single-threaded concurrent
code using coroutines, multiplexing I/O access over sockets and other
resources, running network clients and servers, and other related primitives.
@@ -44,25 +42,40 @@ programming: see the :ref:`Develop with asyncio <asyncio-dev>` page which lists
common traps and explains how to avoid them. :ref:`Enable the debug mode
<asyncio-debug-mode>` during development to detect common issues.
-Table of contents:
+High-level APIs:
.. toctree::
- :maxdepth: 3
+ :maxdepth: 1
- asyncio-eventloop.rst
- asyncio-policy.rst
- asyncio-platforms.rst
asyncio-task.rst
- asyncio-protocol.rst
asyncio-stream.rst
- asyncio-subprocess.rst
asyncio-sync.rst
+ asyncio-subprocess.rst
asyncio-queue.rst
- asyncio-dev.rst
asyncio-exceptions.rst
-.. seealso::
+Low-level APIs:
+
+.. toctree::
+ :maxdepth: 1
- The :mod:`asyncio` module was designed in :PEP:`3156`. For a
- motivational primer on transports and protocols, see :PEP:`3153`.
+ asyncio-eventloop.rst
+ asyncio-future.rst
+ asyncio-protocol.rst
+ asyncio-policy.rst
+ asyncio-platforms.rst
+
+Guides and Tutorials:
+
+.. toctree::
+ :maxdepth: 1
+
+ asyncio-dev.rst
+
+
+.. seealso::
+ The :mod:`asyncio` module was proposed in :PEP:`3156`.
+ Since the acceptance of the PEP many new APIs were added and many
+ original APIs were altered. The PEP should be treated as a
+ historical document.