呼び出しグラフのイントロスペクション
************************************

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

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

asyncio は、実行中の *コルーチン* や *タスク*、または中断中の *Future*
の呼び出しグラフ全体を実行時にたどる、強力なイントロスペクション機能を
備えています。 これらの機能とその基盤の仕組みは、Python プログラム内か
らも、外部のプロファイラーやデバッガーからも利用できます。

参考:

  コマンドラインのイントロスペクションツール
     実行中の別の Python プロセス内のタスクを調べるコマンドラインツー
     ルです。

Added in version 3.14.

asyncio.print_call_graph(future=None, /, *, file=None, depth=1, limit=None)

   現在のタスク、または指定した "Task" や "Future" の非同期呼び出しグ
   ラフを表示します。

   スタックの最上部のフレームから、呼び出し元の起点に向かって順に表示
   します。

   省略可能な *future* 引数を受け取ります。 指定しなければ、現在実行中
   のタスクを使います。

   *現在のタスク* に対して呼び出す場合、省略可能なキーワード専用引数
   *depth* で、スタックの最上部から飛ばすフレーム数を指定できます。

   省略可能なキーワード専用引数 *limit* を指定すると、グラフ内の各コー
   ルスタックのエントリー数を最大 "abs(limit)" 個に制限します。
   *limit* が正なら呼び出し元の起点に近いエントリーを、負ならスタック
   の最上部に近いエントリーを残します。 *limit* を省略するか "None" に
   すると、すべてのエントリーを含めます。 "0" の場合、コールスタックは
   表示せず、何に await されているかの情報だけを表示します。

   *file* を省略するか "None" にすると、"sys.stdout" に出力します。

   **例:**

   次の Python コードは、

      import asyncio

      async def test():
          asyncio.print_call_graph()

      async def main():
          async with asyncio.TaskGroup() as g:
              g.create_task(test(), name='test')

      asyncio.run(main())

   このサンプルコードは以下を出力します:

      * Task(name='test', id=0x1039f0fe0)
      + Call stack:
      |   File 't2.py', line 4, in async test()
      + Awaited by:
         * Task(name='Task-1', id=0x103a5e060)
            + Call stack:
            |   File 'taskgroups.py', line 107, in async TaskGroup.__aexit__()
            |   File 't2.py', line 7, in async main()

asyncio.format_call_graph(future=None, /, *, depth=1, limit=None)

   Like "print_call_graph()", but returns a string. If *future* is
   "None" and there's no current task, the function returns an empty
   string.

asyncio.capture_call_graph(future=None, /, *, depth=1, limit=None)

   現在のタスク、または指定した "Task" や "Future" の非同期呼び出しグ
   ラフを取得します。

   The function receives an optional *future* argument. If not passed,
   the current running task will be used. If there's no current task,
   the function returns "None".

   *現在のタスク* に対して呼び出す場合、省略可能なキーワード専用引数
   *depth* で、スタックの最上部から飛ばすフレーム数を指定できます。

   "FutureCallGraph" データクラスのオブジェクトを返します。

   * "FutureCallGraph(future, call_stack, awaited_by)"

        *future* は "Future" または "Task" (またはそのサブクラス) への
        参照です。

        "call_stack" は "FrameCallGraphEntry" オブジェクトのタプルです
        。

        "awaited_by" は "FutureCallGraph" オブジェクトのタプルです。

   * "FrameCallGraphEntry(frame)"

        *frame* は、コールスタック内の通常の Python 関数のフレームオブ
        ジェクトです。


低水準の補助関数
================

非同期呼び出しグラフを調べるために、asyncio は "shield()" や
"TaskGroup" などの制御フローを扱う仕組みとの連携を必要とします。
"Future.add_done_callback()" のような低水準 API を使う中間的な
"Future" オブジェクトが関わる場合は、次の二つの関数を使ってください。
これにより、その Future が、ラップしたり制御したりするタスクとどうつな
がっているかを asyncio に伝えます。

asyncio.future_add_to_awaited_by(future, waiter, /)

   *future* が *waiter* に await されていることを記録します。

   *future* と *waiter* はどちらも "Future" または "Task"、あるいはそ
   のサブクラスのインスタンスでなければなりません。 それ以外の場合、呼
   び出しても何も起こりません。

   "future_add_to_awaited_by()" を呼び出した後は、いずれ同じ引数で
   "future_discard_from_awaited_by()" を呼び出す必要があります。

asyncio.future_discard_from_awaited_by(future, waiter, /)

   *future* が *waiter* に await されなくなったことを記録します。

   *future* と *waiter* はどちらも "Future" または "Task"、あるいはそ
   のサブクラスのインスタンスでなければなりません。 それ以外の場合、呼
   び出しても何も起こりません。
