> **Источник:** https://python-all.ru/3.16/library/asyncio-graph.html
>
> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.

---

# Интроспекция графа вызовов

**Исходный код:** [Lib/asyncio/graph.py](https://python-all.ru/src/main/Lib/asyncio/graph.py)

---

asyncio предоставляет мощные утилиты для интроспекции графа вызовов во время выполнения, чтобы отследить весь граф вызовов работающей *корутины* или *задачи*, или приостановленного *future*. Эти утилиты и лежащая в основе механика могут использоваться как внутри программы на Python, так и внешними профилировщиками и отладчиками.

Добавлено в версии 3.14.

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

Выводит асинхронный граф вызовов для текущей задачи или переданного [`Task`](https://python-all.ru/3.16/library/asyncio-task.html#asyncio.Task) или [`Future`](https://python-all.ru/3.16/library/asyncio-future.html#asyncio.Future).

Эта функция выводит записи, начиная с верхнего фрейма и двигаясь вниз к точке вызова.

Функция принимает необязательный аргумент *future*. Если он не передан, будет использоваться текущая выполняемая задача.

Если функция вызывается для *текущей задачи*, необязательный именованный аргумент *depth* может использоваться для пропуска указанного количества фреймов с вершины стека.

Если указан необязательный именованный аргумент *limit*, каждый стек вызовов в результирующем графе обрезается так, чтобы включать не более `abs(limit)` записей. Если *limit* положителен, остаются записи, ближайшие к точке вызова. Если *limit* отрицателен, остаются самые верхние записи. Если *limit* опущен или равен `None`, присутствуют все записи. Если *limit* равен `0`, стек вызовов вообще не выводится, выводится только информация «awaited by».

Если *file* опущен или равен `None`, функция будет выводить в [`sys.stdout`](https://python-all.ru/3.16/library/sys.html#sys.stdout).

**Пример:**

Следующий код Python:

```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())
```

выведет:

```python
* 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()`](https://python-all.ru/3.16/library/asyncio-graph.html#asyncio.print_call_graph), но возвращает строку. Если *future* равен `None` и нет текущей задачи, функция возвращает пустую строку.

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

Захватывает асинхронный граф вызовов для текущей задачи или переданного [`Task`](https://python-all.ru/3.16/library/asyncio-task.html#asyncio.Task) или [`Future`](https://python-all.ru/3.16/library/asyncio-future.html#asyncio.Future).

Функция принимает необязательный аргумент *future*. Если он не передан, используется текущая выполняемая задача. Если нет текущей задачи, функция возвращает `None`.

Если функция вызывается для *текущей задачи*, необязательный именованный аргумент *depth* может использоваться для пропуска указанного количества фреймов с вершины стека.

Возвращает объект класса данных `FutureCallGraph`:

- `FutureCallGraph(future, call_stack, awaited_by)`

  > Где *future* – это ссылка на [`Future`](https://python-all.ru/3.16/library/asyncio-future.html#asyncio.Future) или [`Task`](https://python-all.ru/3.16/library/asyncio-task.html#asyncio.Task) (или их подклассы).
  >
  > `call_stack` – это кортеж объектов `FrameCallGraphEntry`.
  >
  > `awaited_by` – это кортеж объектов `FutureCallGraph`.
- `FrameCallGraphEntry(frame)`

  > Где *frame* – это объект фрейма обычной функции Python в стеке вызовов.

## Низкоуровневые вспомогательные функции

Для интроспекции асинхронного графа вызовов asyncio требует содействия от структур управления потоком, таких как [`shield()`](https://python-all.ru/3.16/library/asyncio-task.html#asyncio.shield) или [`TaskGroup`](https://python-all.ru/3.16/library/asyncio-task.html#asyncio.TaskGroup). Всякий раз, когда задействован промежуточный объект [`Future`](https://python-all.ru/3.16/library/asyncio-future.html#asyncio.Future) с низкоуровневыми API, такими как [`Future.add_done_callback()`](https://python-all.ru/3.16/library/asyncio-future.html#asyncio.Future.add_done_callback), следует использовать следующие две функции, чтобы сообщить asyncio о том, как именно такие промежуточные future-объекты связаны с задачами, которые они оборачивают или контролируют.

#### `asyncio.future_add_to_awaited_by(future, waiter, /)`

Записывает, что *future* ожидается объектом *waiter*.

И *future*, и *waiter* должны быть экземплярами [`Future`](https://python-all.ru/3.16/library/asyncio-future.html#asyncio.Future) или [`Task`](https://python-all.ru/3.16/library/asyncio-task.html#asyncio.Task) или их подклассов, иначе вызов не будет иметь эффекта.

Вызов `future_add_to_awaited_by()` должен сопровождаться последующим вызовом функции [`future_discard_from_awaited_by()`](https://python-all.ru/3.16/library/asyncio-graph.html#asyncio.future_discard_from_awaited_by) с теми же аргументами.

#### `asyncio.future_discard_from_awaited_by(future, waiter, /)`

Регистрирует, что *future* больше не ожидается со стороны *waiter*.

Оба *future* и *waiter* должны быть экземплярами [`Future`](https://python-all.ru/3.16/library/asyncio-future.html#asyncio.Future) или [`Task`](https://python-all.ru/3.16/library/asyncio-task.html#asyncio.Task) или их подклассов, иначе вызов не будет иметь эффекта.
