呼叫圖內省（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" 或它們子類別的實例
   ，否則呼叫將不會產生任何效果。
