Spaces:
Running on Zero
A newer version of the Gradio SDK is available: 6.20.0
::: currentmodule asyncio :::
Call Graph Introspection {#asyncio-graph}
Source code: Lib/asyncio/graph.py{.interpreted-text role="source"}
asyncio has powerful runtime call graph introspection utilities to trace the entire call graph of a running coroutine or task, or a suspended future. These utilities and the underlying machinery can be used from within a Python program or by external profilers and debuggers.
::: versionadded 3.14 :::
::: function print_call_graph(future=None, /, *, file=None, depth=1, limit=None)
Print the async call graph for the current task or the provided Task{.interpreted-text role="class"} or Future{.interpreted-text role="class"}.
This function prints entries starting from the top frame and going down towards the invocation point.
The function receives an optional future argument. If not passed, the current running task will be used.
If the function is called on the current task, the optional keyword-only depth argument can be used to skip the specified number of frames from top of the stack.
If the optional keyword-only limit argument is provided, each call stack in the resulting graph is truncated to include at most abs(limit) entries. If limit is positive, the entries left are the closest to the invocation point. If limit is negative, the topmost entries are left. If limit is omitted or None, all entries are present. If limit is 0, the call stack is not printed at all, only "awaited by" information is printed.
If file is omitted or None, the function will print to sys.stdout{.interpreted-text role="data"}.
Example:
The following Python code:
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())
will print:
* 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()
:::
::: function format_call_graph(future=None, /, *, depth=1, limit=None)
Like print_call_graph{.interpreted-text role="func"}, but returns a string. If future is None and there's no current task, the function returns an empty string.
:::
::: function capture_call_graph(future=None, /, *, depth=1, limit=None)
Capture the async call graph for the current task or the provided Task{.interpreted-text role="class"} or Future{.interpreted-text role="class"}.
The function receives an optional future argument. If not passed, the current running task will be used. If there's no current task, the function returns None.
If the function is called on the current task, the optional keyword-only depth argument can be used to skip the specified number of frames from top of the stack.
Returns a FutureCallGraph data class object:
FutureCallGraph(future, call_stack, awaited_by)Where future is a reference to a
Future{.interpreted-text role="class"} or aTask{.interpreted-text role="class"} (or their subclasses.)call_stackis a tuple ofFrameCallGraphEntryobjects.awaited_byis a tuple ofFutureCallGraphobjects.FrameCallGraphEntry(frame)Where frame is a frame object of a regular Python function in the call stack.
:::
Low level utility functions
To introspect an async call graph asyncio requires cooperation from control flow structures, such as shield{.interpreted-text role="func"} or TaskGroup{.interpreted-text role="class"}. Any time an intermediate Future{.interpreted-text role="class"} object with low-level APIs like Future.add_done_callback() <asyncio.Future.add_done_callback>{.interpreted-text role="meth"} is involved, the following two functions should be used to inform asyncio about how exactly such intermediate future objects are connected with the tasks they wrap or control.
::: function future_add_to_awaited_by(future, waiter, /)
Record that future is awaited on by waiter.
Both future and waiter must be instances of Future{.interpreted-text role="class"} or Task{.interpreted-text role="class"} or their subclasses, otherwise the call would have no effect.
A call to future_add_to_awaited_by() must be followed by an eventual call to the future_discard_from_awaited_by{.interpreted-text role="func"} function with the same arguments.
:::
::: function future_discard_from_awaited_by(future, waiter, /)
Record that future is no longer awaited on by waiter.
Both future and waiter must be instances of Future{.interpreted-text role="class"} or Task{.interpreted-text role="class"} or their subclasses, otherwise the call would have no effect.
:::