.. currentmodule:: asyncio

.. _asyncio-dev:

=======================
Developing with asyncio
=======================

Asynchronous programming is different from classic "sequential"
programming.

This page lists common mistakes and traps and explains how
to avoid them.


.. _asyncio-debug-mode:

Debug Mode
==========

By default asyncio runs in production mode.  In order to ease
the development asyncio has a *debug mode*.

There are several ways to enable asyncio debug mode:

* Setting the :envvar:`PYTHONASYNCIODEBUG` environment variable to ``1``.

* Using the :ref:`Python Development Mode <devmode>`.

* Passing ``debug=True`` to :func:`asyncio.run`.

* Calling :meth:`loop.set_debug`.

In addition to enabling the debug mode, consider also:

* setting the log level of the :ref:`asyncio logger <asyncio-logger>` to
  :py:const:`logging.DEBUG`, for example the following snippet of code
  can be run at startup of the application::

    logging.basicConfig(level=logging.DEBUG)

* configuring the :mod:`warnings` module to display
  :exc:`ResourceWarning` warnings.  One way of doing that is by
  using the :option:`-W` ``default`` command line option.


When the debug mode is enabled:

* Many non-threadsafe asyncio APIs (such as :meth:`loop.call_soon` and
  :meth:`loop.call_at` methods) raise an exception if they are called
  from a wrong thread.

* The execution time of the I/O selector is logged if it takes too long to
  perform an I/O operation.

* Callbacks taking longer than 100 milliseconds are logged.  The
  :attr:`loop.slow_callback_duration` attribute can be used to set the
  minimum execution duration in seconds that is considered "slow".


.. _asyncio-multithreading:

Concurrency and Multithreading
==============================

An event loop runs in a thread (typically the main thread) and executes
all callbacks and Tasks in its thread.  While a Task is running in the
event loop, no other Tasks can run in the same thread.  When a Task
executes an ``await`` expression, the running Task gets suspended, and
the event loop executes the next Task.

To schedule a :term:`callback` from another OS thread, the
:meth:`loop.call_soon_threadsafe` method should be used. Example::

    loop.call_soon_threadsafe(callback, *args)

Almost all asyncio objects are not thread safe, which is typically
not a problem unless there is code that works with them from outside
of a Task or a callback.  If there's a need for such code to call a
low-level asyncio API, the :meth:`loop.call_soon_threadsafe` method
should be used, e.g.::

    loop.call_soon_threadsafe(fut.cancel)

To schedule a coroutine object from a different OS thread, the
:func:`run_coroutine_threadsafe` function should be used. It returns a
:class:`concurrent.futures.Future` to access the result::

     async def coro_func():
          return await asyncio.sleep(1, 42)

     # Later in another OS thread:

     future = asyncio.run_coroutine_threadsafe(coro_func(), loop)
     # Wait for the result:
     result = future.result()

To handle signals the event loop must be
run in the main thread.

The :meth:`loop.run_in_executor` method can be used with a
:class:`concurrent.futures.ThreadPoolExecutor` or
:class:`~concurrent.futures.InterpreterPoolExecutor` to execute
blocking code in a different OS thread without blocking the OS thread
that the event loop runs in.

There is currently no way to schedule coroutines or callbacks directly
from a different process (such as one started with
:mod:`multiprocessing`). The :ref:`asyncio-event-loop-methods`
section lists APIs that can read from pipes and watch file descriptors
without blocking the event loop. In addition, asyncio's
:ref:`Subprocess <asyncio-subprocess>` APIs provide a way to start a
process and communicate with it from the event loop. Lastly, the
aforementioned :meth:`loop.run_in_executor` method can also be used
with a :class:`concurrent.futures.ProcessPoolExecutor` to execute
code in a different process.

.. _asyncio-handle-blocking:

Running Blocking Code
=====================

Blocking (CPU-bound) code should not be called directly.  For example,
if a function performs a CPU-intensive calculation for 1 second,
all concurrent asyncio Tasks and IO operations would be delayed
by 1 second.

An executor can be used to run a task in a different thread,
including in a different interpreter, or even in
a different process to avoid blocking the OS thread with the
event loop.  See the :meth:`loop.run_in_executor` method for more
details.


.. _asyncio-logger:

Logging
=======

asyncio uses the :mod:`logging` module and all logging is performed
via the ``"asyncio"`` logger.

The default log level is :py:const:`logging.INFO`, which can be easily
adjusted::

   logging.getLogger("asyncio").setLevel(logging.WARNING)


Network logging can block the event loop. It is recommended to use
a separate thread for handling logs or use non-blocking IO. For example,
see :ref:`blocking-handlers`.


.. _asyncio-coroutine-not-scheduled:

Detect never-awaited coroutines
===============================

When a coroutine function is called, but not awaited
(e.g. ``coro()`` instead of ``await coro()``)
or the coroutine is not scheduled with :meth:`asyncio.create_task`, asyncio
will emit a :exc:`RuntimeWarning`::

    import asyncio

    async def test():
        print("never scheduled")

    async def main():
        test()

    asyncio.run(main())

Output::

  test.py:7: RuntimeWarning: coroutine 'test' was never awaited
    test()

Output in debug mode::

  test.py:7: RuntimeWarning: coroutine 'test' was never awaited
  Coroutine created at (most recent call last)
    File "../t.py", line 9, in <module>
      asyncio.run(main(), debug=True)

    < .. >

    File "../t.py", line 7, in main
      test()
    test()

The usual fix is to either await the coroutine or call the
:meth:`asyncio.create_task` function::

    async def main():
        await test()


Detect never-retrieved exceptions
=================================

If a :meth:`Future.set_exception` is called but the Future object is
never awaited on, the exception would never be propagated to the
user code.  In this case, asyncio would emit a log message when the
Future object is garbage collected.

Example of an unhandled exception::

    import asyncio

    async def bug():
        raise Exception("not consumed")

    async def main():
        asyncio.create_task(bug())

    asyncio.run(main())

Output::

    Task exception was never retrieved
    future: <Task finished coro=<bug() done, defined at test.py:3>
      exception=Exception('not consumed')>

    Traceback (most recent call last):
      File "test.py", line 4, in bug
        raise Exception("not consumed")
    Exception: not consumed

:ref:`Enable the debug mode <asyncio-debug-mode>` to get the
traceback where the task was created::

    asyncio.run(main(), debug=True)

Output in debug mode::

    Task exception was never retrieved
    future: <Task finished coro=<bug() done, defined at test.py:3>
        exception=Exception('not consumed') created at asyncio/tasks.py:321>

    source_traceback: Object created at (most recent call last):
      File "../t.py", line 9, in <module>
        asyncio.run(main(), debug=True)

    < .. >

    Traceback (most recent call last):
      File "../t.py", line 4, in bug
        raise Exception("not consumed")
    Exception: not consumed


Asynchronous generators best practices
======================================

Writing correct and efficient asyncio code requires awareness of certain pitfalls.
This section outlines essential best practices that can save you hours of debugging.


Close asynchronous generators explicitly
----------------------------------------

It is recommended to manually close the
:term:`asynchronous generator <asynchronous generator iterator>`. If a generator
exits early - for example, due to an exception raised in the body of
an ``async for`` loop - its asynchronous cleanup code may run in an
unexpected context. This can occur after the tasks it depends on have completed,
or during the event loop shutdown when the async-generator's garbage collection
hook is called.

To avoid this, explicitly close the generator by calling its
:meth:`~agen.aclose` method, or use the :func:`contextlib.aclosing`
context manager::

  import asyncio
  import contextlib

  async def gen():
    yield 1
    yield 2

  async def func():
    async with contextlib.aclosing(gen()) as g:
      async for x in g:
        break  # Don't iterate until the end

  asyncio.run(func())

As noted above, the cleanup code for these asynchronous generators is deferred.
The following example demonstrates that the finalization of an asynchronous
generator can occur in an unexpected order::

  import asyncio
  work_done = False

  async def cursor():
      try:
          yield 1
      finally:
          assert work_done

  async def rows():
      global work_done
      try:
          yield 2
      finally:
          await asyncio.sleep(0.1) # immitate some async work
          work_done = True


  async def main():
      async for c in cursor():
          async for r in rows():
              break
          break

  asyncio.run(main())

For this example, we get the following output::

  unhandled exception during asyncio.run() shutdown
  task: <Task finished name='Task-3' coro=<<async_generator_athrow without __name__>()> exception=AssertionError()>
  Traceback (most recent call last):
    File "example.py", line 6, in cursor
      yield 1
  asyncio.exceptions.CancelledError

  During handling of the above exception, another exception occurred:

  Traceback (most recent call last):
    File "example.py", line 8, in cursor
      assert work_done
             ^^^^^^^^^
  AssertionError

The ``cursor()`` asynchronous generator was finalized before the ``rows``
generator - an unexpected behavior.

The example can be fixed by explicitly closing the
``cursor`` and ``rows`` async-generators::

  async def main():
      async with contextlib.aclosing(cursor()) as cursor_gen:
          async for c in cursor_gen:
              async with contextlib.aclosing(rows()) as rows_gen:
                  async for r in rows_gen:
                      break
              break


Create asynchronous generators only when the event loop is running
------------------------------------------------------------------

It is recommended to create
:term:`asynchronous generators <asynchronous generator iterator>` only after
the event loop has been created.

To ensure that asynchronous generators close reliably, the event loop uses the
:func:`sys.set_asyncgen_hooks` function to register callback functions. These
callbacks update the list of running asynchronous generators to keep it in a
consistent state.

When the :meth:`loop.shutdown_asyncgens() <asyncio.loop.shutdown_asyncgens>`
function is called, the running generators are stopped gracefully and the
list is cleared.

The asynchronous generator invokes the corresponding system hook during its
first iteration. At the same time, the generator records that the hook has
been called and does not call it again.

Therefore, if iteration begins before the event loop is created,
the event loop will not be able to add the generator to its list of active
generators because the hooks are set after the generator attempts to call them.
Consequently, the event loop will not be able to terminate the generator
if necessary.

Consider the following example::

  import asyncio

  async def agenfn():
      try:
          yield 10
      finally:
          await asyncio.sleep(0)


  with asyncio.Runner() as runner:
      agen = agenfn()
      print(runner.run(anext(agen)))
      del agen

Output::

  10
  Exception ignored while closing generator <async_generator object agenfn at 0x000002F71CD10D70>:
  Traceback (most recent call last):
    File "example.py", line 13, in <module>
      del agen
          ^^^^
  RuntimeError: async generator ignored GeneratorExit

This example can be fixed as follows::

  import asyncio

  async def agenfn():
      try:
          yield 10
      finally:
          await asyncio.sleep(0)

  async def main():
      agen = agenfn()
      print(await anext(agen))
      del agen

  asyncio.run(main())


Avoid concurrent iteration and closure of the same generator
------------------------------------------------------------

Async generators may be reentered while another
:meth:`~agen.__anext__` / :meth:`~agen.athrow` / :meth:`~agen.aclose` call is in
progress. This may lead to an inconsistent state of the async generator and can
cause errors.

Let's consider the following example::

  import asyncio

  async def consumer():
      for idx in range(100):
          await asyncio.sleep(0)
          message = yield idx
          print('received', message)

  async def amain():
      agenerator = consumer()
      await agenerator.asend(None)

      fa = asyncio.create_task(agenerator.asend('A'))
      fb = asyncio.create_task(agenerator.asend('B'))
      await fa
      await fb

  asyncio.run(amain())

Output::

  received A
  Traceback (most recent call last):
    File "test.py", line 38, in <module>
      asyncio.run(amain())
      ~~~~~~~~~~~^^^^^^^^^
    File "Lib/asyncio/runners.py", line 204, in run
      return runner.run(main)
             ~~~~~~~~~~^^^^^^
    File "Lib/asyncio/runners.py", line 127, in run
      return self._loop.run_until_complete(task)
             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
    File "Lib/asyncio/base_events.py", line 719, in run_until_complete
      return future.result()
             ~~~~~~~~~~~~~^^
    File "test.py", line 36, in amain
      await fb
  RuntimeError: anext(): asynchronous generator is already running


Therefore, it is recommended to avoid using asynchronous generators in parallel
tasks or across multiple event loops.
