Документация Python неофициальный перевод
Содержание страницы

26.2. pdb – отладчик Pythonpdb – The Python Debugger

Модуль pdb определяет интерактивный отладчик исходного кода для программ на Python. Он поддерживает установку (условных) точек останова и пошаговое выполнение на уровне строк исходного кода, просмотр стековых кадров, вывод исходного кода и выполнение произвольного кода 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 также можно вызвать как скрипт для отладки других скриптов. Например:

python3 -m pdb myscript.py

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

Обычный способ войти в отладчик из работающей программы – вставить

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]])
Выполняет statement (заданный строкой) под управлением отладчика. Приглашение отладчика появляется перед выполнением любого кода; можно установить точки останова и ввести continue, или выполнять оператор по шагам с помощью step или next (все эти команды описаны ниже). Необязательные аргументы globals и locals задают окружение, в котором выполняется код; по умолчанию используется словарь модуля __main__. (См. описание встроенных функций exec() или eval().)
pdb.runeval(expression[, globals[, locals]])
Вычисляет expression (заданный строкой) под управлением отладчика. Когда runeval() возвращает управление, возвращается значение выражения. В остальном эта функция аналогична run().
pdb.runcall(function[, argument, ...])
Вызывает function (объект функции или метода, не строку) с указанными аргументами. Когда runcall() возвращает управление, возвращается то, что вернул вызов функции. Приглашение отладчика появляется сразу после входа в функцию.
pdb.set_trace()
Выполняет вход в отладчик на стековом фрейме вызвавшей функции. Это полезно для установки точки останова в заданном месте программы, даже если в остальном код не отлаживается (например, при ошибке утверждения).
pdb.post_mortem([traceback])
Запускает посмертную отладку для указанного объекта traceback. Если объект traceback не указан, используется объект traceback текущего обрабатываемого исключения (исключение должно обрабатываться, чтобы значение по умолчанию сработало).
pdb.pm()
Входит в режим посмертной отладки по трассировке, находящейся в sys.last_traceback.

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

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

Pdb – это класс отладчика.

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

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

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

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

Новое в версии 3.1: аргумент skip.

run(statement[, globals[, locals]])
runeval(expression[, globals[, locals]])
runcall(function[, argument, ...])
set_trace()
См. документацию по функциям, описанным выше.

26.2.1. Команды отладчикаDebugger Commands

Отладчик распознаёт следующие команды. Большинство команд можно сократить до одной или двух букв; например, h(elp) означает, что для ввода команды help можно использовать как h, так и 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) [[имя_файла:]номер_строки | функция[, условие]]

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

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

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

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

Задаёт список команд для точки останова с номером bpnumber. Сами команды вводятся на следующих строках. Введите строку, содержащую только ‘end’, чтобы завершить список команд. Пример:

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

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

Без аргумента bpnumber команда commands относится к последней установленной точке останова.

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

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

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

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

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

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

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

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

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

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

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

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

(Pdb) global list_options; list_options = ['-l']
(Pdb)
run [аргументы ...]
Перезапускает отлаживаемую программу Python. Если указан аргумент, он разбивается с помощью “shlex”, и результат используется как новый sys.argv. История, точки останова, действия и параметры отладчика сохраняются. “restart” – псевдоним для “run”.
q(uit)
Выход из отладчика. Выполняемая программа прерывается.

Сноски

[1]Считается ли кадр происходящим из определённого модуля, определяется по __name__ в глобальных переменных кадра.