Есть ли способ подключить отладчик к многопоточному процессу Python?

Я пытаюсь отладить тупик в многопоточном приложении Python после его блокировки. Есть ли способ подключить отладчик для проверки состояния процесса?

Обновлено: я пытаюсь это сделать в Linux, но было бы здорово, если бы было кроссплатформенное решение. В конце концов, это Python :)

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
32
0
30 122
9
Перейти к ответу Данный вопрос помечен как решенный

Ответы 9

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

Обновлено: У меня нет опыта работы с GNU Debugger (GDB), который является кросс-платформенным, однако я нашел этот связь, и он может начать вас на правильном пути. В нем объясняется, как добавить символы отладки (удобно для чтения трассировки стека) и как указать GDB подключиться к запущенному процессу Python.

Ответ принят как подходящий

Да, gdb хорош для отладки нижнего уровня.

Вы можете изменить потоки с помощью команды нить.

например

(gdb) thr 2
[Switching to thread 2 (process 6159 thread 0x3f1b)]
(gdb) backtrace
....

Вы также можете проверить специальные отладчики Python, такие как Winpdb или pydb. Обе платформы независимы.

Если вы имеете в виду pydb, то сделать это невозможно. В этом направлении были предприняты определенные усилия: см. коммит svn, но от него отказались. Якобы winpdb поддерживает это.

Для будущих читателей. Winpdb кажется только python2. Последний выпуск, август 2010 г.) (pypi.org/project/winpdb/#history), и хотя он по-прежнему устанавливается с помощью pip с помощью python3, он не работает при вызове с помощью ModuleNotFoundError: No module named 'SimpleXMLRPCServer'.

gelonida 13.12.2019 16:25

Мой опыт отладки многопоточных программ в PyDev (Eclipse в Windows XP) заключается в том, что потоки, созданные с использованием thread.start_new_thread, не могут быть зацеплены, но поток, созданный с использованием threading.Thread, может быть зацеплен. Надеюсь, информация будет полезной.

Вы можете присоединить отладчик к многопоточному процессу Python, но вам нужно сделать это на уровне C. Чтобы понять, что происходит, вам нужно, чтобы интерпретатор Python был скомпилирован с символами. Если у вас его нет, вам нужно скачать исходный код с python.org и собрать его самостоятельно:

./configure --prefix=/usr/local/pydbg
make OPT=-g
sudo make install
sudo ln -s /usr/local/pydbg/bin/python /usr/local/bin/dbgpy

Убедитесь, что ваша рабочая нагрузка выполняется в этой версии интерпретатора. Затем вы можете присоединиться к нему с помощью GDB в любое время. Разработчики Python включили образец ".gdbinit" в свой каталог Misc, в котором есть несколько полезных макросов. Однако он не работает для многопоточной отладки (!). Вам нужно заменить такие строки

while $pc < Py_Main || $pc > Py_GetArgcArgv

со следующим:

while ($pc < Py_Main || $pc > Py_GetArgcArgv) && ($pc < t_bootstrap || $pc > thread_PyThread_start_new_thread)

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

gdb> attach <PID>
gdb> info threads
gdb> thread <N>
gdb> bt
gdb> pystack
gdb> detach

и посмотрим, что происходит. Что-то вроде.

Вы можете проанализировать, что это за объекты, с помощью макроса «pyo». У Криса есть несколько примеров в своем блоге.

Удачи.

(Привет Блог Дэна за ключевой информацией для меня, в частности исправлением потоковой передачи!)

Используйте Winpdb. Это графический отладчик Python под лицензией GPL независимая платформа с поддержкой удаленной отладки по сети, несколькими потоками, изменением пространства имен, встроенной отладкой, зашифрованной связью и до 20 раз быстрее, чем pdb.

Функции:

  • Лицензия GPL. Winpdb - бесплатное программное обеспечение.
  • Совместимость с CPython 2.3 - 2.6 и Python 3000
  • Совместимость с wxPython с 2.6 по 2.8
  • Независимо от платформы и протестировано на Ubuntu Gutsy и Windows XP.
  • Пользовательские интерфейсы: rpdb2 основан на консоли, а winpdb требует wxPython 2.6 или новее.

Screenshot
(source: winpdb.org)

как указано в характеристиках: сегодня, когда python2 почти мертв, к сожалению, это уже не так полезно.

gelonida 13.12.2019 16:27

pdbinject позволяет вам внедрить pdb в уже запущенный процесс Python.

Исполняемый файл pdbinject работает только под python2, но также может внедряться в python3.

PyCharm IDE позволяет подключаться к запущенному процессу Python, начиная с версии 4.0.

Здесь описано, как это сделать.

Сайт 404. Пожалуйста, укажите шаги здесь.

luckydonald 09.02.2018 11:09

Это можно использовать как мертвый простой "удаленный" отладчик:

import sys
import socket
import pdb

def remote_trace():
    server = socket.socket()
    server.bind(('0.0.0.0', 12345))
    server.listen()
    client, _= server.accept()
    stream = client.makefile('rw')
    sys.stdin = sys.stdout = sys.stderr = stream
    pdb.set_trace()

remote_trace()

# Execute in the shell: `telnet 127.0.0.1 12345`

В Windows проще использовать Netcat вместо Telnet (который также работает в Linux).

Другие вопросы по теме