Отображение stack trace работы python-приложения в реальном времени
Пройдите тест, узнайте какой профессии подходите
Быстрый ответ
Для отображения трассировки стека актуальных вызовов в Python-приложении используйте traceback.print_exc()
. Этот метод выводит трассировку исключений, в случае их появления. Если исключений нет, то traceback.print_stack()
покажет трассировку с текущего момента выполнения кода:
import traceback
# Получение трассировки для исключения
try:
# Код, где может возникнуть ошибка...
except Exception:
# Вывод трассировки стека при возникновении исключения
traceback.print_exc()
# Вывод трассировки стека без исключения
traceback.print_stack()
Приведенный код нужно вставить в те места, где требуется анализ вызовов или информация об ошибке.
Переход в режим отладки с помощью сигналов
На Unix-системах для входа в режим отладки работающего приложения можно использовать сигналы:
import signal
import pdb
def interrupt_handler(sig, frame):
# Переход в режим отладчика
pdb.set_trace()
signal.signal(signal.SIGUSR1, interrupt_handler)
Сигнал отправляется следующей командой:
kill -SIGUSR1 <pid>
После этого вы окажетесь в интерактивной сессии отладчика pdb, где сможете изучить переменные и ход выполнения кода. Чтобы выйти из режима отладчика, нажмите Ctrl+D.
Нужно быть осторожным, такой подход может оказать влияние на ввод/вывод.
Тихие фоновые процессы
Для мониторинга фоновых процессов предпочтительнее использовать внешний скрипт. Эффективный подход в этом случае предложен в Python cookbook (ссылка на рецепт).
Gdb для трассировки уровней стека
Для анализа стека используйте gdb (Grand Debugger):
gdb python <pid>
Не забудьте подготовить файл python-specific gdbinit для использования команды pystack
, которая позволяет рассмотреть стек. Если при работе gdb начнут возникать проблемы с ptrace
, можно применить следующий хак:
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
Pyrasite — ненавязчивый наблюдатель
Pyrasite интегрируется в процесс и возвращает трассировку стека, не вмешиваясь при этом в его работу:
sudo pyrasite <pid> dump_stacks.py
Проверьте совместимость Pyrasite с вашей системой перед использованием.
Сбор информации о стеке с использованием threading
, sys
и traceback
В многопоточном приложении для сбора информации о стеках можно использовать данный фрагмент кода:
import threading
import sys
import traceback
def dump_stacks(signal, frame):
id_to_name = {th.ident: th.name for th in threading.enumerate()}
code = []
for thread_id, stack in sys._current_frames().items():
code.append(f"\n# Поток: {id_to_name.get(thread_id,'')}({thread_id})")
for filename, lineno, name, line in traceback.extract_stack(stack):
code.append(f'Файл: "{filename}", строка {lineno}, в {name}')
if line:
code.append(f" {line.strip()}")
print("\n".join(code))
signal.signal(signal.SIGUSR2, dump_stacks)
Обработка сигналов поможет вам получить информацию о стеке из различных потоков.
Управление многопоточным хаосом
В многопоточной среде перед проведением любых операций со стеком необходимо удостовериться в безопасности потоков и целостности данных.
Визуализация
Для визуализации стека в вашем приложении используйте:
import traceback
def print_stack():
stack = traceback.format_stack()
print(''.join(stack))
Использование traceback.format_stack()
помогает проследить путь выполнения кода, как тщательно оформленный отчет.
Секретные чертежи: strace
strace
может быть использован для мониторинга системных вызовов внутри Python-приложений, но этот инструмент не является специфичным для Python.