Как дебажить asyncio корутины с GDB?

Есть расширение, которое позволяет использовать GDB для дебага Питонячих процессов, я его установил и попробовал использовать на моём веб-приложении на aiohttp. Но, какие бы запросы там не выполнялись, в консоли всегда отображается самый базовый стэк вызовов, без какой-либо полезной информации:

(gdb) py-bt
Traceback (most recent call first):
  File "/usr/lib/python3.7/selectors.py", line 468, in select
    fd_event_list = self._selector.poll(timeout, max_ev)
  File "/usr/lib/python3.7/asyncio/base_events.py", line 1739, in _run_once
    event_list = self._selector.select(timeout)
  File "/usr/lib/python3.7/asyncio/base_events.py", line 539, in run_forever
    self._run_once()
  File "/usr/lib/python3.7/asyncio/base_events.py", line 571, in run_until_complete
    self.run_forever()
  File "/usr/local/lib/python3.7/dist-packages/aiohttp/web.py", line 433, in run_app
    reuse_port=reuse_port))
  File "./my-server/main.py", line 98, in <module>
    web.run_app(app_main, host=host, port=port)

Вероятно это следствие того, что asyncio создаёт свой стэк вызовов каждой корутине.

Мне очень важно иметь возможность смотреть внутренности процесса для дебага нагруженного веб-приложения. Как можно посмотреть стэк вызовов и прерывать/продолжать корутины с GDB?


Ответы (1 шт):

Автор решения: AivanF.

После долгих поисков удалось найти альтернативное решение, утилита py-spy! В отличие от gdb, ей не нужен запуск целевого процесса на специальной сборке Питона, а также она не испытывает трудностей при работе с асинхронными функциями. Простой пример использования:

pip install py-spy

# Получить стэки вызовов активных потоков:
py-spy dump --pid 1

# Смотреть выполняющиеся функции в реалтайме:
py-spy top --pid 1

Подробное описание можно найти здесь: https://github.com/benfred/py-spy

Важное для некоторых окружений замечание: как и gdb, для использования внутри Докера этой утилите нужен включенный флаг SYS_PTRACE.

→ Ссылка