Command-line introspection tools
********************************

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

======================================================================

The "asyncio" module can be invoked as a script via "python -m
asyncio" to inspect the task graph of another running Python process
without modifying it or restarting it.  The "asyncio.tools" submodule
implements this interface.

The following commands inspect the process identified by "PID":

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

The commands read the target process state without executing any code
in it. They are only available on supported platforms and may require
permission to inspect another process.  See the permission
requirements for details.

See also:

  Call graph introspection
     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:

example.py

   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()}")
       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:

   $ 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.

Added in version 3.14.


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

pstree PID

   Display task and coroutine relationships as a tree.  Each task is
   shown with its full coroutine stack, nested under the task (if any)
   that is awaiting it.  This subcommand is useful for quickly
   identifying which branch of a task hierarchy is blocked and where
   in its coroutine stack execution has paused:

      $ 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

   If the await graph contains a cycle, "pstree" reports an error
   instead of printing a tree.  A cycle in the await graph is unusual
   and typically indicates a programming error:

      $ python -m asyncio pstree 12345
      ERROR: await-graph contains cycles - cannot print a tree!

      cycle: Task-2 → Task-3 → Task-2

ps PID

   Display a flat table of all pending tasks in the process *PID*.
   Each row shows the event-loop thread ID, task ID and name,
   coroutine stack, and the awaiting task’s stack, name, and ID, if
   any.

   This subcommand prints all tasks regardless of whether the await
   graph contains cycles:

      $ 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

--retries N

   Retry failed attempts to inspect the target process up to *N*
   times.  This can help when the target process changes while its
   state is being read.

   Added in version 3.15.
