# 呼叫圖內省（Call Graph Introspection）

原始碼：Lib/asyncio/graph.py

asyncio 擁有強大的 runtime 呼叫圖內省工具，可以追蹤執行中的協程或任務，或是暫停的 future 的完整呼叫圖。這些工具和底層機制可以在 Python 程式內部使用，或被外部分析器和偵錯器使用。

在 3.14 版被加入.

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

  印出目前任務或所提供的 `Task` 或 `Future` 的非同步呼叫圖。

  此函式會從頂層 frame 開始印出條目，然後往下到呼叫點。

  此函式接受一個選擇性的 future 引數。如果未傳入，將使用目前執行中的任務。

  如果在目前任務上呼叫此函式，可以使用選擇性的僅限關鍵字引數 depth 來跳過堆疊頂端指定數量的 frame。

  如果提供了選擇性的僅限關鍵字引數 limit，結果圖中的每個呼叫堆疊會被截斷為最多包含 `abs(limit)` 個條目。如果 limit 為正數，保留的條目是最接近呼叫點的。如果 limit 為負數，保留最頂層的條目。如果 limit 被省略或為 `None`，則顯示所有條目。如果 limit 為 `0`，則完全不印出呼叫堆疊，只印出「awaited by」資訊。

  如果 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)

  類似於 `print_call_graph()`，但回傳一個字串。如果 future 為 `None` 且沒有目前任務，此函式回傳一個空字串。

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

  捕獲目前任務或所提供的 `Task` 或 `Future` 的非同步呼叫圖。

  此函式接受一個選擇性的 future 引數。如果未傳入，將使用目前執行中的任務。如果沒有目前任務，此函式回傳 `None`。

  如果在目前任務上呼叫此函式，可以使用選擇性的僅限關鍵字引數 depth 來跳過堆疊頂端指定數量的 frame。

  會回傳一個 `FutureCallGraph` 資料類別物件：

  - `FutureCallGraph(future, call_stack, awaited_by)`

    > 其中 future 是對 `Future` 或 `Task`（或它們的子類別）的參照。

    > `call_stack` 是一個由 `FrameCallGraphEntry` 物件組成的元組。

    > `awaited_by` 是一個由 `FutureCallGraph` 物件組成的元組。

  - `FrameCallGraphEntry(frame)`

    > 其中 frame 是呼叫堆疊中常規 Python 函式的 frame 物件。

## 低階工具函式

要內省非同步呼叫圖，asyncio 需要來自控制流程結構的協作，例如 `shield()` 或 `TaskGroup`。任何時候涉及使用低階 API（如 `Future.add_done_callback()`）的中介 `Future` 物件時，應使用以下兩個函式來告知 asyncio 這些中介 future 物件如何與它們所包裝或控制的任務連接。

asyncio.future_add_to_awaited_by(future, waiter, /)

  記錄 future 正被 waiter 等待。

  future 和 waiter 都必須是 `Future` 或 `Task` 或它們子類別的實例，否則呼叫將不會產生任何效果。

  對 `future_add_to_awaited_by()` 的呼叫必須最終跟隨一個對 `future_discard_from_awaited_by()` 函式的呼叫，並使用相同的引數。

asyncio.future_discard_from_awaited_by(future, waiter, /)

  記錄 future 不再被 waiter 等待。

  future 和 waiter 都必須是 `Future` 或 `Task` 或它們子類別的實例，否則呼叫將不會產生任何效果。