Подтвердить что ты не робот

Как я могу узнать, где висит мой python script?

Итак, я отлаживаю программу python и обнаружил ошибку, которая заставляет программу зависать, как в бесконечном цикле. Теперь у меня была проблема с бесконечным циклом раньше, но когда он зависает, я могу убить программу, а python выплюнул полезное исключение, которое сообщило мне, когда программа завершилась, когда я отправил команду kill. Теперь, однако, когда программа зависает, и я ctrl-c, она не прерывается, но продолжает работать. Есть ли какой-нибудь инструмент, который я могу использовать для поиска повесить трубку? Я новичок в профилировании, но из того, что я знаю, профилировщик может предоставить вам информацию о успешно завершенной программе. Или вы можете использовать профилировщик для отладки таких зависаний?

4b9b3361

Ответ 1

Предположим, что вы используете свою программу как:

python YOURSCRIPT.py

Попробуйте запустить вашу программу как:

python -m trace --trace YOURSCRIPT.py

И имейте некоторое терпение, пока на экране напечатано множество материалов. Если у вас бесконечный цикл, он будет продолжаться постоянно (проблема с остановкой). Если он застрял где-то, то в основном вы застряли на вводе/выводе, или это тупик.

Ответ 2

Вау! Уже 5 ответов, и никто не предложил самое очевидное и простое:

  1. Попробуйте найти воспроизводимый контрольный пример, который вызывает зависание.
  2. Добавьте запись в ваш код. Это может быть так же просто, как print "**010", print "**020" и т.д., Пронизывающих основные области.
  3. Запустите код. Посмотрите, где это висит. Не могу понять почему? Добавьте больше регистрации. (То есть, если между ** 020 и ** 030, перейдите и добавьте ** 023, ** 025, ** 027 и т.д.)
  4. Перейти к 3.

Ответ 3

Если ваша программа слишком велика и сложна, чтобы быть жизнеспособной для одиночного шага с помощью pdb или распечатывать каждую строку с помощью модуля трассировки, тогда вы можете попробовать трюк из моих дней программирования 8-битных игр. Начиная с версии Python 2.5, pdb имеет возможность связывать код с точкой останова с помощью команды commands. Вы можете использовать это для печати сообщения и продолжения работы:

(Pdb) commands 1
(com) print "*** Breakpoint 1 ***"
(com) continue
(com) end
(Pdb)

Это приведет к печати сообщения и продолжению работы при ударе точки останова 1. Определите аналогичные команды для нескольких других точек останова.

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

Кстати, на 8-битных микросах (Commodore 64, Spectrum и т.д.) вы могли бы выставить значение в место реестра, чтобы изменить цвет границы вокруг экрана. Я использовал несколько точек останова, чтобы сделать это с разными цветами, поэтому, когда программа запускается, будет отображаться психоделический дисплей радуги, пока он не будет виден, тогда граница изменится на один цвет, который расскажет вам, что такое последняя точка останова. Вы также можете хорошо относиться к относительной производительности разных разделов кода на количество каждого цвета в радуге. Иногда я скучаю по этой простоте в этих новых висячих машинах Windows.

Ответ 4

Я написал модуль, который выводит потоки длиной до 10 секунд в одном месте. hanging_threads.py

Вот пример вывода:

--------------------    Thread 5588     --------------------
  File "C:\python33\lib\threading.py", line 844, in _exitfunc
        t.join()
  File "C:\python33\lib\threading.py", line 743, in join
        self._block.wait()
  File "C:\python33\lib\threading.py", line 184, in wait
        waiter.acquire()

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

Ответ 5

Легче предотвратить эти зависания, чем отлаживать их.

Во-первых: циклы for очень и очень сложно застревать в ситуации, когда цикл не заканчивается. Очень сложно.

Второе: петли while относительно легко застревают в цикле.

Первый проход - проверить каждый цикл while, чтобы убедиться, что он должен быть циклом while. Часто вы можете заменить конструкторы while на for, и вы исправите свою проблему, переосмыслив свой цикл.

Если вы не можете заменить цикл while на for, вам просто нужно доказать, что выражение в выражении while должно меняться каждый раз через цикл. Это не так сложно доказать.

  • Посмотрите на все условия в цикле. Назовите этот T.

  • Посмотрите на все ветки логики в теле цикла. Есть ли способ пройти через цикл без внесения изменений в условие, T?

    • Да? Это твоя ошибка. Этот логический путь неверен.

    • Нет? Отлично, что цикл должен завершаться.

Ответ 6

Если ваша программа слишком сложна, чтобы просто отслеживать все функции, вы можете попробовать запустить ее и вручную добавить программу-трассировку, например lptrace к нему. Он немного похож на strace - он печатает каждый вызов функции, который делает ваша программа. Вот как это называется:

python lptrace -p $STUCK_PROGRAM_PID

Обратите внимание, что для lptrace требуется запустить gdb.

Ответ 7

Ничего, как старый добрый pdb

import pdb
pdb.run('my_method()',globals(),locals())

Затем просто нажмите (n), чтобы перейти к следующей команде, чтобы войти. см. документы для полной справки. Следуйте своей программе шаг за шагом, и вы, вероятно, быстро ее выясните.

Ответ 9

Не использовал его сам, но я слышал, что Eric IDE хорош и имеет хороший отладчик. Это также единственная IDE, которую я знаю об этом, имеет отладчик для Python

Ответ 10

Если ваша программа имеет несколько потоков, она может игнорировать ctrl-c, потому что один поток подключен к обработчику ctrl-c, но поток live (runaway?) глух к нему. GIL (глобальная блокировка интерпретатора) в CPython означает, что, как правило, только один поток может быть запущен в любой момент времени. Я думаю, что я решил свою (возможно) аналогичную проблему, используя this

Ответ 11

i = 0
for t in threading.enumerate():
    if i != 0:# and t.getName() != 'Thread-1':
        print t.getName()
        t._Thread__stop()
    i += 1

Как только вы узнаете имена потоков; перезапустите ваш script и отфильтруйте их, не останавливая их от прерывания. я = 0 условие предотвращает прерывание основного потока.

Я предлагаю пройти и называть все ваши потоки; такие как: Thread (target = self.log_sequence_status, name= "статус журнала" )

Этот код должен быть помещен в конец основной программы, которая запускает процесс прогона

Ответ 12

Ничего себе! Кажется, вы добавили столько кода за один раз, не тестируя его, что не можете сказать, какой код был добавлен, прежде чем программа начала зависать... (наиболее вероятная причина проблемы).

Серьезно, вы должны кодировать небольшими шагами и тестировать каждый отдельно (в идеале делать TDD).

Для вашей точной проблемы определения того, что работает python-код, и ctrl-c не работает, я попытаюсь выполнить необдуманное предположение: использовали ли вы except: исключение всех исключений. Если вы сделали это в цикле (и продолжаете цикл после управления исключением), это очень вероятная причина, по которой ctrl-c не работает: он ухватился за это исключение. Измените на except Exception:, и его больше не нужно улавливать (есть другие возможности для ctrl + c, которые не работают как управление потоками, как предлагал другой плакат, но я считаю, что вышеприведенная причина более вероятна).

исключение KeyboardInterrupt

Raised when the user hits the interrupt key (normally Control-C or Delete). 

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

Changed in version 2.5: Changed to inherit from BaseException.