呼叫圖自省

原始碼: Lib/asyncio/graph.py


asyncio 具有強大的執行時呼叫圖自省工具,可以跟蹤正在執行的 協程任務,或暫停的 future 的整個呼叫圖。這些工具和底層機制可以從 Python 程式內部使用,也可以由外部分析器和偵錯程式使用。

在 3.14 版本加入。

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

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

此函式從頂部幀開始列印條目,並向下指向呼叫點。

此函式接收一個可選的 future 引數。如果未傳入,將使用當前正在執行的任務。

如果此函式在 當前任務 上呼叫,可選的僅限關鍵字 depth 引數可用於跳過棧頂指定數量的幀。

如果提供了可選的僅限關鍵字 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 引數可用於跳過棧頂指定數量的幀。

返回一個 FutureCallGraph 資料類物件

  • FutureCallGraph(future, call_stack, awaited_by)

    其中 future 是對 FutureTask(或其子類)的引用。

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

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

  • FrameCallGraphEntry(frame)

    其中 frame 是呼叫棧中常規 Python 函式的幀物件。

低階實用函式

為了自省非同步呼叫圖,asyncio 需要控制流結構(例如 shield()TaskGroup)的協作。任何時候涉及具有 Future.add_done_callback() 等低階 API 的中間 Future 物件時,都應該使用以下兩個函式來告知 asyncio 這些中間 Future 物件與它們封裝或控制的任務之間究竟是如何連線的。

asyncio.future_add_to_awaited_by(future, waiter, /)

記錄 futurewaiter 等待。

futurewaiter 都必須是 FutureTask 或其子類的例項,否則呼叫將無效。

呼叫 future_add_to_awaited_by() 後必須最終呼叫 future_discard_from_awaited_by() 函式,並使用相同的引數。

asyncio.future_discard_from_awaited_by(future, waiter, /)

記錄 future 不再被 waiter 等待。

futurewaiter 都必須是 FutureTask 或其子類的例項,否則呼叫將無效。