pdb — Отладчик Python

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

Отладчик расширяем — он определяет класс Pdb. На данный момент это не задокументированно, но достаточно легко можно понять из исходного кода. Интерфейс расширений использует модули bdb и cmd.

Приглашением отладчика является (Pdb). Обычный пример запуска программы под отладчиком таков:

>>> import pdb
>>> import mymodule
>>> pdb.run('mymodule.test()')
> <string>(0)?()
(Pdb) continue
> <string>(1)?()
(Pdb) continue
NameError: 'spam'
> <string>(1)?()
(Pdb)

pdb.py может быть вызван и как скрипт для отладки других скриптов. Например:

python -m pdb myscript.py

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

New in version 2.4: Был добавлен перезапуск при “посмертной” отладке.

Типичный способ засунуть отладчик в запущенную программу - добавить:

import pdb; pdb.set_trace()

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

Типичное использование - исследование “падающей” программы:

>>> import pdb
>>> import mymodule
>>> mymodule.test()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "./mymodule.py", line 4, in test
    test2()
  File "./mymodule.py", line 3, in test2
    print spam
NameError: spam
>>> pdb.pm()
> ./mymodule.py(3)test2()
-> print spam
(Pdb)

Модуль определяет следующие функции; каждая из них запускает отладчик по совему:

pdb.run(statement[, globals[, locals]])[source]

Выполняет выражение statement (заданное строкой) под контролем отладчика. Приглашение отладчика возникает перед тем, как будет выполнен какой либо код. Вы можете задать точки прерывания и набрать continue, или вы можете пройтись по коду при помощи step или next (все эти команды описаны ниже). Не обязательные аргументы globals и locals определяют окружение в котором будет выполнен код. По умолчанию используоется словарь модуля __main__. (Смотрите объяснение выражения exec или встроенной функции eval().)

pdb.runeval(expression[, globals[, locals]])[source]

Выполняет выражение expression (данное в виде строки) под контролем отладчика. Когда функция runeval() завершается, она возвращает значение выражения. Во всём остальном эта функция аналогична run().

pdb.runcall(function[, argument, ...])[source]

Вызывает function (объект функции или метода, не строку) с указанными аргументами. Когда runcall() завершается, возвращает то, что возвращает вызванная функция. Приглашение отладчика возникает при входе в функцию.

pdb.set_trace()[source]

Вход в режим отладки начинается при вызове фрейма. Это полезно для жёсткой вставки точки прерывания в программу, даже если по другому код отладить нельзя (например, если возникает исключение).

pdb.post_mortem([traceback])[source]

Начинает “посмертную” отладку для данного объекта traceback. Если traceback не задан, то используется то исключение, которое на данный момент обрабатывается (в этом случае исключение должно перехватываться).

pdb.pm()[source]

Начинает “посмертную” отладку трассировки, находящейся в sys.last_traceback.

Функции run* и set_trace() являются синонимами для экземпляров класса Pdb и вызывают его методы с соответствующим именем. Если вы хотите получить доступ к следующим возможностям, вы должны делать это сами:

class pdb.Pdb(completekey='tab', stdin=None, stdout=None, skip=None)[source]

Pdb является классом отладчика.

Аргументы completekey, stdin и stdout передаются нижлежащему классу cmd.Cmd; смотрите его описание.

Аргумент skip, если указан, должен быть итерируемым и выдавать шаблоны имён модулей в glob-стиле. Отладчик не будет входить в фреймы из модулей, которые соответствуют одному из этих шаблонов. [1]

Пример вызова для трассировки с skip:

import pdb; pdb.Pdb(skip=['django.*']).set_trace()

New in version 2.7: Аргумент skip.

run(statement[, globals[, locals]])
runeval(expression[, globals[, locals]])
runcall(function[, argument, ...])
set_trace()

Смотрите описание функции выше.

Команды отладчика

Отладчик знает следующие команды. Большая их часть может быть сокращена до одной-двух букв, например h(elp) означает, что можно использовать либо h, либо help для ввода команды help (но не he, hel, H, Help или HELP). Аргументы команды должны быть разделены пробелами (пробелами или табуляцией). Не обязательные аргументы заключены в квадратные скобки ([]) в описании синтаксиса команды, вводить их не надо. Альтернативы в описании синтаксиса разделены вертикальной чертой (|).

Ввод пустой строки повторяет последнюю введённую команду. Но если последняя команда была list, то будут выведены следующие 11 строк.

Если отладчик не может распознать команду, он предполагает, что ввод является выражением Python и выполняет его в контесте отлаживаемой программы. Выражения Python так же можно предварять восклицательным знаком (!). Это замечательный способ исследовать отлаживаемую программу. Более того, можно даже изменять занчение переменной или вызвать функцию. Если в таком выражении возникает исключение, то выводится имя исключения, но состояние отладчика не меняется.

На одной строке можно ввести несколько команд, они должны быть разделены
;;. (Одиночный ; не искользуется, так как он является разделителем для команд в строке, которые передаются интерпретатору Python.) В

разделении команд нет ничего хитрого - ввод разделяется на первой паре ;; даже если он находится в середине строки в кавычках.

Отладчик поддерживает “псевдонимы”. Псевдонимы могут иметь параметры, которые позволяют приспособить его к исследуемому контексту.

Если файл .pdbrc находится к домашнем каталоге пользователя или в текущем каталоге, то он прочитывается и выполняется, как если бы его содержание было введено в ответ на приглашение отладчика. Это особенно полезно для псевдонимов. Если существует оба файла, то сперва прочитывается файл из домашнего каталога и псевдонимы, определённые там, могут быть переопределены в локальном файле.

h(elp) [command]
Без аргумента выведет список доступных команд. С аргументов;м command выведен помощь для этой команды. help pdb отобразит файл документации. Если определена переменная окружения PAGER, файл будет передан через эту команду. Так как аргумент command должен быть идентификатором, для того, чтобы получить помощь о команде !, необходимо ввести help exec.
w(here)
Выводит трассировку, где более поздний фрейм находится ниже. Стрелка обозначает текущий фрейм, который определяет контекст большинства комманд.
d(own)
Перемещает текущий ферйм на уровень вниз в стеке (к более новому фрейму).
u(p)
Перемещает текущий ферйм на уровень вверх в стеке (к более старому фрейму).
b(reak) [[filename:]lineno | function[, condition]]

С аргументом lineno, устанавливает точку останова в текущем файле на указанной строке. С аргументом function, устанавливает точку останова на первом выполнимом выражении в этой функции. Номер строки можно предварить именем файла и двоеточием, чтобы установить точку останова в другом файле (возможно даже в том, который ещё не был загружен). Файл ищется в sys.path. Обратите внимание, что каждой точке останова присваивается номер, который используется другими командами для этих точек.

Если указан второй аргумент, то он должен быть выражением, которое должно быть истинно до того, как точка останова is honored.

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

tbreak [[filename:]lineno | function[, condition]]
Временная точка останова, которая автоматически удаляется при первом срабатывании. Аргументы аналогичны команде break.
cl(ear) [filename:lineno | bpnumber [bpnumber ...]]
Если указан аргумент filename:lineno, удаляет все точки останова на указаной строке. Если указан список номеров точек останова, разделённых пробелами, удаляет точки из этого списка. Без аргументов - удаляет все точки (предварительно запросив подтверждение).
disable [bpnumber [bpnumber ...]]
Отключает точки останова, переданные как список номеров, разделённый запятыми. Отключение точки доступа означает, что она не вызывает остановки в процессе выполнения программы, но в отличие от удаления точки останова, она остаётся в списке точек и её можно заново включить.
enable [bpnumber [bpnumber ...]]
Включает указанные точки останова.
ignore bpnumber [count]
Устанавливает счётчик игнорирования для заданной по номеруточки останова. Если count не указан, то устанавливается в 0. Точка останова активируется, когда счётчик игнорирования равен 0. Если он не равен 0, то он уменьшается на 1 каждый раз, когда выполнение доходит до этой точки, точка не отключена и все ассоциированные условия истины.
condition bpnumber [condition]
Условие - это выражение, которое должно быть вычислено и оказаться истинным до того, как происходит остановка на точке останова. Если условие отсутствует, то тогда точка останова становится безусловной.
commands [bpnumber]

Определяет набор команд для точки останова с номером bpnumber. Сами команды указываются на следующих строках. Для того, чтобы закончить ввод команд, введите ‘end’. Например:

(Pdb) commands 1
(com) print some_variable
(com) end
(Pdb)

Чтобы удалить все команды с точки останова наберите commands и затем сразу end; это значит отсутствие комманд.

Если аргумент bpnumber не указан, команды будут адресованы последней установленной точке останова.

Вы можете использовать команды точки останова для того, чтобы снова запустить свою программу. Для этого используйте команду continue, или step, или любую другую команду, которая продолжает выполнение.

Определение команды, продолжающей выполнение (на данный момент, это continue, step, next, return, jump, quit и их аббревиатуры) прерывает список команд (как если бы за этой командой сразу шёл end). Причина этого в том, что каждый раз, когда вы продолжаете выполнение (даже командами next или step), вы можете столкнуться с другой точкой останова, у которой может быть свой собственный список команд, приводящий к неоднозначности по поводу того, какой из списков надо выполнить.

Если вы используете команду ‘silent’ в списке команд, то обычное сообщение об остановке не будет выведено. Это может быть желательно для точек останова, которые выводят специальное сообщение и продолжают выполнение программы. Если никакая команда ничего не выводит, то у вас не будет никакого знака того, что была достигнута точка останова.

New in version 2.5.

s(tep)
Выполняет текущую строку, останавливаясь на первой возможной позиции (либо в функции, которая была вызывана, либо на следующей строке текущей функции).
n(ext)
Продолжает выполнение до следующей строки функции или её завершения. (Разница между next и step в том, что step останавливает выполнение внутри вызванной функции, тогда как next выполняет вызванную функцию на (почти) максимальной скорости и останавливает выполнение на следующей строке в текущей функции.)
unt(il)

Продолжает выполнение пока номер строки не станет больше номера текущей строки или пока не будет совершён выход из текущего фрейма.

New in version 2.6.

r(eturn)
Продолжает выполение до завершения текущей функции.
c(ont(inue))
Продолжает выполнение до ближайшей точки останова.
j(ump) lineno

Задаёт следующую строку, которая должна быть выполнена. Доступно только в самом нижнем фрейме. Это позволяет вам “прыгнуть” назад и ещё раз пройти код, или прыгнуть вперёд и пропустить код, который вы не хотите выполнять.

Надо отметить, что можно сделать не любой прыжок – например, не возможно прыгунть в средину цикла for или из выражения finally.

l(ist) [first[, last]]
Выводит исходный код для текущего файла. Без аргументов будет выведено 11 строк вокруг текущей строки или продолжение предыдущего листинга. С одним аргументом выведет 11 строк около этой строки. С двумя аргументами, выведет выведет строки из данного диапазона; если второй аргумент меньше первого, то он интерпретируется как количество строк, которые надо вывести.
a(rgs)
Выводит список аргументов для текущей функции.
p expression

Вычисляет выражение expression в текущем контексте и выводит вычисленное значение.

Note

Можно использовать и print, но это не команда отладчика — это приведёт к выполнению выражения Python print.

pp expression
Аналогично команде p, за исключением того, что значение выводится при помощи модуля pprint.
alias [name [command]]

Создаёт псевдоним с именем name, который выполняет command. Команда не должна быть заключена в кавычки. Заменяемые параметры могут быть обозначены как %1, %2 и т.д., а %* заменяет все параметры. Если команда не указана, то показывается текущий псевдоним для name. Если аргументы не заданы, то перечисляются все псевдонимы.

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

В качестве примера тут приводится два полезных псевдонима (особенно когда они помещены в файл .pdbrc):

#Вывести переменные экзмепляра (пример: "pi classInst")
alias pi for k in %1.__dict__.keys(): print "%1.",k,"=",%1.__dict__[k]
#Вывести переменные в self
alias ps pi self
unalias name
Удаляет заданный псевдоним.
[!]statement

Выполняет (однострочное) выражение statement в контексте текущего фрейма. Восклицательный знак может быть опущен в случае, если первое слово выражения не является командой отладчика. Для того, чтобы установить глобальную переменную, вы можете предварить команду установки командой global, то есть:

(Pdb) global list_options; list_options = ['-l']
(Pdb)
run [args ...]

Перезапускает программу отладки. Если указан аргумент, то он делится при помощи “shlex” (shlex) и результат используется как новый sys.argv. История, точки останова и опции отладчика сохраняются. “restart” является псевдонимом “run”.

New in version 2.6.

q(uit)
Выходит из отладчика. Исполняемая программа прерывается.

Footnotes

[1]Соответствует ли фрейм исходному в определённом модуле определяется по __name__ в глобальных переменных фрейма.