コマンドラインのイントロスペクションツール
******************************************

**ソースコード:** Lib/asyncio/tools.py

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

"asyncio" モジュールは "python -m asyncio" でスクリプトとして実行でき
、実行中の別の Python プロセスを変更したり再起動したりせずに、そのタス
クグラフを調べられます。 このインターフェースは "asyncio.tools" サブモ
ジュールが実装しています。

次のコマンドは、"PID" で指定したプロセスを調べます。

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

これらのコマンドは、対象プロセス内でコードを実行せずに、その状態を読み
取ります。 サポートされているプラットフォームでのみ利用でき、別のプロ
セスを調べるための権限が必要な場合があります。 詳しくは 必要な権限 を
参照してください。

参考:

  呼び出しグラフのイントロスペクション
     現在のプロセス内の Task や Future の非同期呼び出しグラフを、プロ
     グラムから調べるための API です。

以下のコマンド例では、調査用のタスク階層を作成してプロセス 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())

1 つの端末でプログラムを起動し、実行したままにします。

   $ python example.py
   PID: 12345

次に、表示されたプロセス ID を、別の端末からコマンドに渡します。 スレ
ッド ID、タスク ID、ファイルパス、行番号は、実行時やソースコードの配置
によって異なります。

Added in version 3.14.


コマンドラインオプション
========================

pstree PID

   タスクとコルーチンの関係をツリーとして表示します。 各タスクはコルー
   チンのスタック全体とともに表示され、そのタスクを await しているタス
   クがあれば、その下に入れ子で配置されます。 このサブコマンドは、タス
   ク階層のどの枝がブロックしていて、コルーチンのスタックのどこで実行
   が止まっているかを素早く把握するのに役立ちます。

      $ 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

   await の関係を表すグラフに循環がある場合、"pstree" はツリーを表示せ
   ずにエラーを報告します。 このグラフに循環があるのはまれで、通常はプ
   ログラムの誤りを示します。

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

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

ps PID

   プロセス *PID* 内の未完了のタスクをすべて、階層のない表で表示します
   。 各行には、イベントループのスレッド ID、タスクの ID と名前、コル
   ーチンのスタックを表示します。 そのタスクを await しているタスクが
   あれば、そのスタック、名前、ID も表示します。

   このサブコマンドは、await の関係を表すグラフに循環があるかどうかに
   かかわらず、すべてのタスクを表示します。

      $ 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

   対象プロセスの調査に失敗した場合、最大 *N* 回再試行します。 状態の
   読み取り中に対象プロセスが変化する場合に役立ちます。

   Added in version 3.15.
