24 марта 2012 г. IPython PuDB Django pdb Python Debug

Отладка Python/Django при помощи PuDB

Этим отладчиком я пользуюсь недавно, где-то полгода, может чуть больше. До этого обходился (надо признаться мучался) с pdb, а также print'ами, logger'ом, debug_toolbar'ом и т.д. Главное отличие в том, что у PuDB есть графический интерфейс с подсветкой синтаксиса, панелями для вывода дополнительной информации, интеграцией с IPython, удобными хоткеями и т.д., всё это делает его незаменимым инструмент на каждый день!

Автор: Andreas Klöckner
Страница проекта на PyPI: http://pypi.python.org/pypi/pudb
Исходный код проекта на GitHub или в GitWeb автора
Текущая версия: 2012.1

Отладчик использует urwid для построения графического интерфейса и pygments для подсветки синтаксиса.

Установка и настройка

Всё предельно просто, ставим из PyPI:

pip install pudb

Или из исходников:

git clone git://github.com/inducer/pudb.git
cd pudb && setup.py install
# либо сделайте симлинк в site-packages (я так обычно делаю, использую virtualenv и пакеты из транка)
ln -s ~/pudb/pudb ~/venv/<virtualenv>/lib/python2.7/site-packages/pudb

Запустите PuDB:

$ python
>>> import pudb
>>> pudb.set_trace()

Перед вами предстанет отладчик и попросит вас его настроить, а если не попросит, то можно вызвать настройки самостоятельно - нажмите "Ctrl+p". Там вы сможете выбрать shell (classic или ipython), тему (classic, vim, dark vim, midnight, либо создать тему самому), порядок вывода стека, способ вывода значений переменных контекста (type, str, repr, либо собственная реализация).

Инструкция по применению

Сразу надо заметить, что в интерфейсе сразу все понятно что к чему, а если что-то не понятно, то надо нажать "?" и вы увидите полный "help". Приведу его только часть, в порядке частоты использования:

Основное:

! - вызвать shell, при этом будет доступен весь контекст в котором вы находитесь
o - вывести консоль, но только для просмотра, удобно когда вы вводили что-то в консоле и хотите снова это посмотреть

n - "step over" (перешагнуть), перейти к следующей строке кода
s - "step into", перейти во внутрь объекта, если это возможно, иначе перейти к следующей строке кода
u - подняться на один стек-фрейм вверх
d - опуститься на один стек-фрейм вниз

c - "continue", продолжить (до первого брейкпоинта или до завершения работы программы)
f - завершить текущую функцию
q - выход из отладчика и продолжение работы программы

e - показать трейсбек, при этом вы сначала в шапке отладчика отчётливо увидите что произошол трейсбек
L - показать путь до текущего файла и номер строки, а также goto-line
/ - поиск строки ("," - вперед, "." - назад)

Работа с брейкпоинтами:

b - установить брейкпоинт
enter - отредактировать брейкопинт (работает в панели брейкпоинтов)
d - удалить брейкпоинт (работает в панели брейкпоинтов)

Работа с панелями:

V - перейти в панель Variables
S - перейти в панель Stack
B - перейти в панель Breakpoints
+/- - расширить/сузить панель в ширину
_/= - минимализировать/максимализировать панель в ширину
[/] - расширить/сузить панель в высоту

Работа с панелью переменных (Variables):

\ - развернуть/свернуть содержимое переменной
t/r/s/c - переключаться между type/repr/str/custom форматом вывода переменной
h - подсветить переменную в панели (также и отключает подсветку)
@ - закрепить переменную в верхней части панели
w - переключится в режим word-wrap для переменных (и обратно также)
n/Insert - добавить в верхнюю панель выражение для слежения (например вы ожидаете появления переменной "test_something", то добавьте её название, когда она будет доступна, тогда появится в верхней панели со значением)
enter - управление переменными в Variables, в том числе и удаление

Интеграция с Django и IPython

До версии PuDB 2012.1 необходимо было сделать следующие манипуляции, если по каким-либо причинам вы используете старую версию PuDB, то вам это должно пригодится. В новой версии ничего делать не надо, всё работает из коробки!

Также с IPython (версии 0.13+) и PuDB до версии 2012.1 были проблемы, но если вы используете IPython 0.10.x (который до сих пор в пакетах Ubuntu как основной), то всё будет хорошо. Вот, к слову, о PuDB+IPython интергации.

Использование

Приведу пару примеров о том как пользоваться PuDB:

# Запуск отладчика для определенного скрипта
python -m pudb.run script.py
python -m pudb.run manage.py runcpdebug
# Далее, устанавливайте брейкпоинты и жмите "c" (Continue),
#   как только отладчик дойдёт до брейкпоинта он остановится

В коде можно вызвать так:

# В любом месте вставьте:
import pudb; pudb.set_trace()

Ко всему прочему привожу видеокаст от автора:

PuDB Intro Screencast from Andreas Klöckner on Vimeo.

Реализация установки брейкпоинтов для Emacs

Так как я пользуюсь Emacs, то решил для него сделать функцию и хот-кей для вставки брейкпоинта в PuDB.
Поместите следующий код в свой "~/.emacs":

(defun pudb-save-breakpoint ()
  (interactive)
  (setq file (buffer-file-name))
  (setq line (substring (what-line) 5))
  (setq saved-breakpoints "~/.config/pudb/saved-breakpoints")
  (with-temp-buffer
    (insert "b " file ":" line "\n")
    (when (file-writable-p saved-breakpoints)
      (append-to-file (point-min)
                    (point-max)
                    saved-breakpoints)))
)
(global-set-key [?\C-x ?\C-_] 'pudb-save-breakpoint)

Идея простая, все брейкпоинты PuDB пишет в свой файл "~/.config/pudb/saved-breakpoints", в формате:

b <file>:<line>
b <file>:<line>

Воспользоваться этим как видите очень просто - надо дописывать брейкпоинты. Также можно реализовать удаление брейкпоинта, очистку (в том числе с неймспейсом по проекту) и т.д., но мне пока и этого достаточно. Если кто знает готовый или хочет сделать полноценный модуль для Emacs+PuDB, то пишите, буду очень рад!

Так как в elisp я особо не силён, то можно сделать python-скрипт, в который elisp будет передавать аргументы, а скрипт будет уже делать все манипуляции с файлом брейкпоинтов.

Также, рекомендую ознакомиться со списком отладчиков для python: PythonDebuggers - PythonInfo Wiki.

Комментарии

Если вдруг PuDB не работает, то скорее всего у вас может быть случай, когда запущенное приложение все пишет в stderr, как было у меня со Scrapy.
Следующий код исправит данный недуг:


# scrapy_project/__init__.py
import sys
import pyjack

def fakeimport(orgopen, *a, **kw):
    if args[0] is "pudb":
        sys.stdout = sys.__stderr__
    return orgopen(*a, **kw)

pyjack.connect(__import__, proxyfn=fakeimport)

ps. Используется пакет pyjack для манкипатчинга

Если скрипт запущенный с PuDB виснет сильно (в сравнении с тем когда без PuDB), то возможно виноват Variables (с режимами "str" или "repr"), надо в настройках указать режим "type", чтобы не выводились значения переменных контекста, а в нужных местах переключать режим (хоткеи: "s" или "r" соответственно) или вообще использовать shell (хоткей "!").

Пофиксил дублирование брейкпоинтов https://github.com/inducer/pudb/pull/39

Буду использовать.
Как вернутся в основную панель после перехода в Variables?

Нажать на клавишу влево "<-"

Спасибо!

Возможно устанавливать значения для переменных? В консоли могу, но в блоке Variables значение не поменялось

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

Оставьте свой комментарий

Markdown