Присоединение процесса с помощью pdb

У меня есть сценарий python, который я подозреваю, что есть тупик. Я пытался отлаживать pdb но если я шаг за шагом, он не получает тупик, и по возвращенному результату я вижу, что он не вешается на той же итерации. Я хотел бы прикрепить свой сценарий к отладчику только тогда, когда он заблокирован, возможно ли это? Я открыт для использования других отладчиков, если это необходимо.

2 Solutions collect form web for “Присоединение процесса с помощью pdb”

В настоящее время pdb не имеет возможности остановить и начать отладку в запущенной программе. У вас есть еще несколько вариантов:

GDB

Вы можете использовать GDB для отладки на уровне C. Это немного абстрактнее, потому что вы пишете исходный код Python, а не ваш реальный скрипт Python, но это может быть полезно для некоторых случаев. Инструкции приведены здесь: https://wiki.python.org/moin/DebuggingWithGdb . Они слишком вовлечены, чтобы обобщить здесь.

Расширения и модули сторонних производителей

Просто googling для «процесса присоединения pdb» показывает пару проектов, чтобы дать PDB эту способность:
Pyringe: https://github.com/google/pyringe
Pycharm: https://blog.jetbrains.com/pycharm/2015/02/feature-spotlight-python-debugger-and-attach-to-process/
Эта страница вики Python имеет несколько альтернатив: https://wiki.python.org/moin/PythonDebuggingTools


Для вашего конкретного случая использования у меня есть некоторые идеи для обходных решений:

сигналы

Если вы используете unix, вы можете использовать такие сигналы, как в этом сообщении в блоге, чтобы попытаться остановить и прикрепить к запущенному скрипту.

Этот блок цитат скопирован непосредственно из связанного сообщения в блоге:

Конечно, pdb уже получил функции для запуска отладчика в середине вашей программы, в первую очередь pdb.set_trace (). Однако это требует от вас знать, где вы хотите начать отладку, это также означает, что вы не можете оставить его для производственного кода.

Но я всегда завидовал тому, что я могу сделать с GDB: просто прервите запущенную программу и начните суетиться с помощью отладчика. Это может быть удобно в некоторых ситуациях, например, вы застреваете в цикле и хотите исследовать. И сегодня мне вдруг пришло в голову: просто зарегистрируйте обработчик сигнала, который устанавливает функцию трассировки! Здесь доказательство кода концепции:

 import os import signal import sys import time def handle_pdb(sig, frame): import pdb pdb.Pdb().set_trace(frame) def loop(): while True: x = 'foo' time.sleep(0.2) if __name__ == '__main__': signal.signal(signal.SIGUSR1, handle_pdb) print(os.getpid()) loop() 

Теперь я могу отправить SIGUSR1 в запущенное приложение и получить отладчик. Прекрасный!

Я полагаю, вы могли бы оживить это, используя Winpdb для обеспечения удаленной отладки в случае, если ваше приложение больше не привязано к терминалу. И другая проблема, указанная выше, заключается в том, что она не может возобновить выполнение программы после вызова pdb, после выхода из pdb вы просто получите трассировку и выполняете (но поскольку это только bdb, поднимающее исключение bdb.BdbQuit, я думаю это можно решить несколькими способами). Последняя проблема связана с Windows, я мало что знаю о Windows, но я знаю, что у них нет сигналов, поэтому я не уверен, как вы могли это сделать.

Условные точки останова и циклы

Вы все еще можете использовать PDB, если у вас нет доступных сигналов, если вы завершаете захват блокировки или семафора в цикле, который увеличивает счетчик, и останавливается только тогда, когда счетчик достигает смехотворно большого количества. Например, предположим, что у вас есть блокировка, которую вы подозреваете, является частью вашего тупика:

 lock.acquire() # some lock or semaphore from threading or multiprocessing 

Перепишите это так:

 count = 0 while not lock.acquire(False): # Start a loop that will be infinite if deadlocked count += 1 continue # now set a conditional breakpoint here in PDB that will only trigger when # count is a ridiculously large number: # pdb> <filename:linenumber>, count=9999999999 

Точка останова должна срабатывать, когда счет очень велик (надеюсь), указывая на то, что там произошел тупик. Если вы обнаружите, что это срабатывает, когда объекты блокировки, похоже, не указывают на тупик, тогда вам может понадобиться вставить короткую задержку в цикле, чтобы он не увеличивался достаточно быстро. Возможно, вам также придется играть с порогом срабатывания точки останова, чтобы заставить его запускаться в нужное время. Число в моем примере было произвольным.

Другим вариантом этого было бы не использовать PDB и преднамеренно создавать исключение, когда счетчик становится огромным, вместо запуска точки останова. Если вы пишете свой собственный класс исключений, вы можете использовать его для объединения всех локальных состояний семафора / блокировки в исключение, а затем перехватите его на верхнем уровне вашего скрипта, чтобы распечатать его прямо перед выходом.

Индикаторы файлов

Другой способ, которым вы можете использовать свой тупиковый цикл, не полагаясь на правильность получения счетчиков, – это вместо этого записать в файлы:

 import time while not lock.acquire(False): # Start a loop that will be infinite if deadlocked with open('checkpoint_a.txt', 'a') as fo: # open a unique filename fo.write("\nHit") # write indicator to file time.sleep(3) # pause for a moment so the file size doesn't explode 

Теперь пусть ваша программа заработает минуту или две. Убейте программу и пройдите через эти файлы «контрольной точки». Если тупик отвечает за вашу застопоренную программу, файлы, в которых есть слово «hit», написанное в них несколько раз, указывают, какие блокировки несут ответственность за ваш тупик.

Вы можете расширить полезность этого, указав переменные печати цикла или другую информацию состояния, а не только константу. Например, вы сказали, что подозреваете, что тупик происходит в цикле, но не знаю, на какой итерации он включен. Пусть этот цикл блокировки дампирует управляющие переменные вашего цикла или другую информацию о состоянии, чтобы идентифицировать итерацию, на которой произошел тупик.

Существует клон pdb, образно называемый pdb-clone , который может присоединяться к запущенному процессу .

Вы просто добавляете from pdb_clone import pdbhandler; pdbhandler.register() from pdb_clone import pdbhandler; pdbhandler.register() в код основного процесса, а затем вы можете запустить pdb с помощью pdb-attach --kill --pid PID .

  • Отладка программ python в emacs
  • Каков самый простой способ использования Pdon pdb для проверки причины необработанного исключения?
  • Emacs python-mode: сочетания клавиш для пошаговой отладки pdb
  • Отладочная колба с pdb
  • Тестирование модулей Python: автоматический запуск отладчика при неудачном тестировании
  • Не удалось ли импортировать модуль (но не использовать его) в Python?
  • Установка Theano на Windows - загрузка DLL не выполнена
  • Как отлаживать приложение Django, работающее на Heroku, используя удаленное соединение pdb?
  • Python - лучший язык программирования в мире.