呼叫圖內省(Graph Introspection)

原始碼:Lib/asyncio/graph.py


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

在 3.14 版被加入.

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

印出當前任務或所提供的 TaskFuture 的非同步呼叫圖。

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

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

如果在當前任務上呼叫此函式,可以使用選擇性的僅限關鍵字引數 depth 來跳過堆疊頂端指定數量的框架(frames)。

如果提供了選擇性的僅限關鍵字引數 limit,結果圖中的每個呼叫堆疊會被截斷為最多包含 abs(limit) 個條目。如果 limit 為正數,保留的條目是最接近呼叫點的。如果 limit 為負數,保留最頂層的條目。如果 limit 被省略或為 None,則顯示所有條目。如果 limit0,則完全不印出呼叫堆疊,只印出「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(),但回傳一個字串。如果 futureNone 且沒有當前任務,此函式回傳一個空字串。

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

捕獲當前任務或所提供的 TaskFuture 的非同步呼叫圖。

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

如果在當前任務上呼叫此函式,可以使用選擇性的僅限關鍵字引數 depth 來跳過堆疊頂端指定數量的框架(frames)。

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

  • FutureCallGraph(future, call_stack, awaited_by)

    其中 future 是對 FutureTask(或它們的子類別)的參照。

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

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

  • FrameCallGraphEntry(frame)

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

低階工具函式

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

asyncio.future_add_to_awaited_by(future, waiter, /)

記錄 future 正被 waiter 等待。

futurewaiter 都必須是 FutureTask 或它們子類別的實例,否則呼叫將不會產生任何效果。

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

asyncio.future_discard_from_awaited_by(future, waiter, /)

記錄 future 不再被 waiter 等待。

futurewaiter 都必須是 FutureTask 或它們子類別的實例,否則呼叫將不會產生任何效果。