Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion Doc/library/asyncio-graph.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
.. _asyncio-graph:

========================
Call Graph Introspection
Call graph introspection
========================

**Source code:** :source:`Lib/asyncio/graph.py`
Expand All @@ -17,6 +17,12 @@ a suspended *future*. These utilities and the underlying machinery
can be used from within a Python program or by external profilers
and debuggers.

.. seealso::

:ref:`asyncio-introspection-tools`
Command-line tools for inspecting tasks in another running Python
process.

.. versionadded:: 3.14


Expand Down
136 changes: 136 additions & 0 deletions Doc/library/asyncio-tools.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
.. currentmodule:: asyncio

.. _asyncio-introspection-tools:

================================
Command-line introspection tools
================================

**Source code:** :source:`Lib/asyncio/tools.py`

-------------------------------------

The :mod:`!asyncio` module can be executed as a script to inspect asyncio
tasks in another Python process:

.. code-block:: shell-session

$ python -m asyncio ps [--retries N] PID
$ python -m asyncio pstree [--retries N] PID

``PID`` is the process ID of the Python process to inspect. The commands use
Python's :ref:`remote debugging support <remote-debugging>` to read the target
process state, but do not execute code in the target process. They are only
available on supported platforms and may require permission to inspect another
process. See :ref:`permission-requirements` for details.

.. seealso::

:ref:`asyncio-graph`
Programmatic APIs for inspecting the async call graph of a task or
future in the current process.

The command examples below use this program, which creates a task hierarchy
suitable for inspection and prints its process ID:

.. code-block:: python

import asyncio
import os

async def play(track):
await asyncio.sleep(3600)
print(f"🎵 Finished: {track}")

async def album(name, tracks):
async with asyncio.TaskGroup() as tg:
for track in tracks:
tg.create_task(play(track), name=track)

async def main():
print(f"PID: {os.getpid()}", flush=True)
async with asyncio.TaskGroup() as tg:
tg.create_task(
album("Sundowning", ["TNDNBTG", "Levitate"]),
name="Sundowning",
)
tg.create_task(
album("TMBTE", ["DYWTYLM", "Aqua Regia"]),
name="TMBTE",
)

asyncio.run(main())

Run the program in one terminal and leave it running:

.. code-block:: shell-session

$ python example.py
PID: 12345

Then pass the printed process ID to the commands from another terminal.
Thread IDs, task IDs, file paths, and line numbers vary between runs and
source layouts.

.. versionadded:: 3.14

Command-line options
====================

.. option:: ps PID

Display a table of pending tasks in the process *PID*. The table includes
the thread ID, task ID, task name, coroutine stack, awaiter chain, awaiter
name, and awaiter ID:

.. code-block:: shell-session

$ python -m asyncio ps 12345
tid task id task name coroutine stack awaiter chain awaiter name awaiter id
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
18445801 0x10a456060 Task-1 TaskGroup._aexit -> TaskGroup.__aexit__ -> main 0x0
18445801 0x10a439f60 Sundowning TaskGroup._aexit -> TaskGroup.__aexit__ -> album TaskGroup._aexit -> TaskGroup.__aexit__ -> main Task-1 0x10a456060
18445801 0x10a439d70 TMBTE TaskGroup._aexit -> TaskGroup.__aexit__ -> album TaskGroup._aexit -> TaskGroup.__aexit__ -> main Task-1 0x10a456060
18445801 0x10a2a3a80 TNDNBTG sleep -> play TaskGroup._aexit -> TaskGroup.__aexit__ -> album Sundowning 0x10a439f60
18445801 0x10a2a38a0 Levitate sleep -> play TaskGroup._aexit -> TaskGroup.__aexit__ -> album Sundowning 0x10a439f60
18445801 0x10a2d7150 DYWTYLM sleep -> play TaskGroup._aexit -> TaskGroup.__aexit__ -> album TMBTE 0x10a439d70
18445801 0x10a6bdaa0 Aqua Regia sleep -> play TaskGroup._aexit -> TaskGroup.__aexit__ -> album TMBTE 0x10a439d70

.. option:: pstree PID

Display the same task and coroutine relationships as a tree:

.. code-block:: shell-session

$ python -m asyncio pstree 12345
└── (T) Task-1
└── main example.py:12
└── TaskGroup.__aexit__ Lib/asyncio/taskgroups.py:75
└── TaskGroup._aexit Lib/asyncio/taskgroups.py:124
├── (T) Sundowning
│ └── album example.py:7
│ └── TaskGroup.__aexit__ Lib/asyncio/taskgroups.py:75
│ └── TaskGroup._aexit Lib/asyncio/taskgroups.py:124
│ ├── (T) TNDNBTG
│ │ └── play example.py:4
│ │ └── sleep Lib/asyncio/tasks.py:702
│ └── (T) Levitate
│ └── play example.py:4
│ └── sleep Lib/asyncio/tasks.py:702
└── (T) TMBTE
└── album example.py:7
└── TaskGroup.__aexit__ Lib/asyncio/taskgroups.py:75
└── TaskGroup._aexit Lib/asyncio/taskgroups.py:124
├── (T) DYWTYLM
│ └── play example.py:4
│ └── sleep Lib/asyncio/tasks.py:702
└── (T) Aqua Regia
└── play example.py:4
└── sleep Lib/asyncio/tasks.py:702

.. option:: --retries N

Retry failed attempts to inspect the target process up to *N* times. See
:ref:`sampling-efficiency` for details about failed process memory reads.

.. versionadded:: 3.15
13 changes: 13 additions & 0 deletions Doc/library/asyncio.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ asyncio provides a set of **high-level** APIs to:

* :ref:`synchronize <asyncio-sync>` concurrent code;

There are also **introspection** APIs and tools for:

* inspecting the :ref:`async call graph <asyncio-graph>` of tasks and futures;

* inspecting tasks in another running Python process with
:ref:`command-line tools <asyncio-introspection-tools>`;

Additionally, there are **low-level** APIs for
*library and framework developers* to:

Expand Down Expand Up @@ -108,7 +115,13 @@ for full functionality and the latest features.
asyncio-subprocess.rst
asyncio-queue.rst
asyncio-exceptions.rst

.. toctree::
:caption: Introspection APIs
:maxdepth: 1

asyncio-graph.rst
asyncio-tools.rst

.. toctree::
:caption: Low-level APIs
Expand Down
Loading