调用图内省
**********

**源代码:** Lib/asyncio/graph.py

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

asyncio 具有强大的运行时调用图内省工具，可以跟踪正在运行的 *协程* 或 *
任务* 或挂起的 *future* 的整个调用图。这些工具和底层机制可以在 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* 为负数，则保留最上面的项。如果
   *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* 参数可用于
   从堆栈顶部跳过指定的帧数。

   返回一个 "FutureCallGraph" 数据类对象：

   * "FutureCallGraph(future, call_stack, awaited_by)"

        其中 *future* 是一个指向 "Future" 或 "Task" (或其子类) 的引用
        。

        "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* 等待。

   *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" 或它们的子类的实例
   ，否则该调用将不起作用。
