pdb
— Отладчик Python¶
Исходный код: Lib/pdb.py
Модуль pdb
определяет интерактивный отладчик исходного кода для программ на Python. Он поддерживает установку (условных) точек останова и однократное пошаговое выполнение на уровне строки исходного кода, проверку стековых фреймов, листинг исходного кода и оценку произвольного кода на Python в контексте любого стекового фрейма. Он также поддерживает посмертную отладку и может быть вызван под программным управлением.
Отладчик является расширяемым - на самом деле он определен как класс Pdb
. В настоящее время это не задокументировано, но легко понять, прочитав исходный код. Интерфейс расширения использует модули bdb
и cmd
.
См.также
- Модуль
faulthandler
Используется для явного сброса данных трассировки Python при сбое, по истечении таймаута или по сигналу пользователя.
- Модуль
traceback
Стандартный интерфейс для извлечения, форматирования и печати трассировок стека программ на Python.
Типичным способом проникновения в отладчик является вставка:
import pdb; pdb.set_trace()
Или:
breakpoint()
в том месте, где вы хотите запустить отладчик, а затем запустите программу. Затем вы можете выполнить пошаговое выполнение кода, следующего за этой инструкцией, и продолжить работу без отладчика, используя команду continue
.
Изменено в версии 3.7: Встроенный breakpoint()
, вызываемый по умолчанию, может использоваться вместо import pdb; pdb.set_trace()
.
def double(x):
breakpoint()
return x * 2
val = 3
print(f"{val} * 2 is {double(val)}")
В приглашении отладчика отображается (Pdb)
, что указывает на то, что вы находитесь в режиме отладки:
> ...(3)double()
-> return x * 2
(Pdb) p x
3
(Pdb) continue
3 * 2 is 6
Изменено в версии 3.3: Для команд и аргументов команд доступно заполнение вкладок с помощью модуля readline
, например, текущие глобальные и локальные имена предлагаются в качестве аргументов команды p
.
Вы также можете вызвать pdb
из командной строки для отладки других скриптов. Например:
python -m pdb myscript.py
При вызове в качестве модуля pdb автоматически переходит к посмертной отладке, если отлаживаемая программа завершает работу нештатно. После посмертной отладки (или после нормального завершения работы программы) pdb перезапускает программу. Автоматический перезапуск сохраняет состояние pdb (например, точки останова) и в большинстве случаев более полезен, чем выход из отладчика после завершения работы программы.
Изменено в версии 3.2: Добавлена опция -c
для выполнения команд, как если бы они были заданы в файле .pdbrc
; смотрите Команды отладчика.
Изменено в версии 3.7: Добавлена опция -m
для выполнения модулей аналогично тому, как это делает python -m
. Как и в случае со сценарием, отладчик приостанавливает выполнение непосредственно перед первой строкой модуля.
Типичным способом выполнения инструкции под управлением отладчика является:
>>> import pdb
>>> def f(x):
... print(1 / x)
>>> pdb.run("f(2)")
> <string>(1)<module>()
(Pdb) continue
0.5
>>>
Типичным способом проверки вышедшей из строя программы является:
>>> import pdb
>>> def f(x):
... print(1 / x)
...
>>> f(0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in f
ZeroDivisionError: division by zero
>>> pdb.pm()
> <stdin>(2)f()
(Pdb) p x
0
(Pdb)
Модуль определяет следующие функции; каждая из них поступает в отладчик несколько иным способом:
- pdb.run(statement, globals=None, locals=None)¶
Выполните инструкцию * (заданную в виде строки или объекта кода) под управлением отладчика. Приглашение отладчика появляется перед выполнением любого кода; вы можете установить точки останова и ввести
continue
или выполнить пошаговую инструкцию, используяstep
илиnext
(все эти команды описаны ниже). Необязательные аргументы globals и locals указывают среду, в которой выполняется код; по умолчанию используется словарь модуля__main__
. (Смотрите описание встроенных функцийexec()
илиeval()
.)
- pdb.runeval(expression, globals=None, locals=None)¶
Вычислите выражение (заданное в виде строки или объекта кода) под управлением отладчика. При возврате
runeval()
возвращается значение выражения. В противном случае эта функция аналогичнаrun()
.
- pdb.runcall(function, *args, **kwds)¶
Вызовите function (объект функции или метода, а не строку) с заданными аргументами. Когда
runcall()
возвращает значение, которое было возвращено вызовом функции. Приглашение отладчика появляется сразу после ввода функции.
- pdb.set_trace(*, header=None)¶
Введите команду отладчика в вызывающем фрейме стека. Это полезно для жесткого кодирования точки останова в заданной точке программы, даже если код не отлаживается иным образом (например, при сбое утверждения). Если задан, то header выводится на консоль непосредственно перед началом отладки.
Изменено в версии 3.7: Аргумент только для ключевого слова header.
- pdb.post_mortem(traceback=None)¶
Введите посмертную отладку данного объекта обратной трассировки. Если параметр обратной трассировки не задан, используется одно из обрабатываемых в данный момент исключений (исключение должно обрабатываться, если используется значение по умолчанию).
- pdb.pm()¶
Введите посмертную отладку обратной трассировки, найденной в
sys.last_traceback
.
Функции run*
и set_trace()
являются псевдонимами для создания экземпляра класса Pdb
и вызова метода с тем же именем. Если вы хотите получить доступ к дополнительным функциям, вам придется сделать это самостоятельно:
- class pdb.Pdb(completekey='tab', stdin=None, stdout=None, skip=None, nosigint=False, readrc=True)¶
Pdb
- это класс отладчика.Аргументы completekey, stdin и stdout передаются в базовый класс
cmd.Cmd
; смотрите описание там.Аргумент skip, если он задан, должен быть повторяемым из шаблонов имен модулей в стиле glob. Отладчик не будет переходить к фреймам, которые исходят из модуля, соответствующего одному из этих шаблонов. [1]
По умолчанию Pdb устанавливает обработчик для сигнала SIGINT (который отправляется, когда пользователь нажимает Ctrl-C на консоли), когда вы даете команду
continue
. Это позволит вам снова войти в отладчик, нажав Ctrl-C. Если вы хотите, чтобы Pdb не касался обработчика SIGINT, установите для nosigint значение true.Аргумент readrc по умолчанию имеет значение true и определяет, будет ли Pdb загружать файлы .pdbrc из файловой системы.
Пример вызова для включения трассировки с помощью skip:
import pdb; pdb.Pdb(skip=['django.*']).set_trace()
Выдает auditing event
pdb.Pdb
без каких-либо аргументов.Изменено в версии 3.1: Добавлен параметр пропустить.
Изменено в версии 3.2: Добавлен параметр nosigint. Ранее Pdb никогда не устанавливал обработчик SIGINT.
Изменено в версии 3.6: Аргумент readrc.
Команды отладчика¶
Ниже перечислены команды, распознанные отладчиком. Большинство команд могут быть сокращены до одной или двух букв, как указано; например, h(elp)
означает, что для ввода команды help можно использовать либо h
, либо help
(но не he
или hel
, ни H
, ни Help
, ни HELP
). Аргументы команд должны разделяться пробелами (пробелами или символами табуляции). Необязательные аргументы заключаются в квадратные скобки ([]
) в синтаксисе команд; квадратные скобки не должны вводиться. Варианты в синтаксисе команды разделены вертикальной чертой (|
).
Ввод пустой строки повторяет последнюю введенную команду. Исключение: если последней командой была команда list
, будут перечислены следующие 11 строк.
Команды, которые отладчик не распознает, считаются инструкциями Python и выполняются в контексте отлаживаемой программы. Инструкции Python также могут сопровождаться восклицательным знаком (!
). Это эффективный способ проверки отлаживаемой программы; можно даже изменить переменную или вызвать функцию. Когда в такой инструкции возникает исключение, выводится имя исключения, но состояние отладчика не изменяется.
Отладчик поддерживает aliases. Псевдонимы могут иметь параметры, которые обеспечивают определенный уровень адаптации к рассматриваемому контексту.
В одной строке может быть введено несколько команд, разделенных символом ;;
. (Одиночный символ ;
не используется, поскольку он служит разделителем для нескольких команд в строке, передаваемой синтаксическому анализатору Python.) Для разделения команд не применяется никакой логики; входные данные разделяются на первой паре ;;
, даже если они находятся в середине строки, заключенной в кавычки. Обходным путем для строк с двойными точками с запятой является использование неявной конкатенации строк ';'';'
или ";"";"
.
Если файл .pdbrc
существует в домашнем каталоге пользователя или в текущем каталоге, он считывается с кодировкой 'utf-8'
и выполняется так, как если бы он был введен в командной строке отладчика, за исключением пустых строк и строк, начинающихся с #
игнорируются. Это особенно полезно для псевдонимов. Если оба файла существуют, то сначала считывается тот, который находится в домашнем каталоге, и определенные там псевдонимы могут быть заменены локальным файлом.
Изменено в версии 3.2: .pdbrc
теперь может содержать команды, которые продолжают отладку, такие как continue
или next
. Ранее эти команды не действовали.
Изменено в версии 3.11: .pdbrc
теперь считывается в кодировке 'utf-8'
. Ранее оно считывалось в кодировке, соответствующей языковому стандарту системы.
- h(elp) [command]¶
Без указания аргумента выведите список доступных команд. Указав command в качестве аргумента, выведите справку по этой команде.
help pdb
отображает полную документацию (строку документации модуляpdb
). Поскольку аргумент command должен быть идентификатором, для получения справки по команде!
необходимо ввестиhelp exec
.
- w(here)¶
Выведите трассировку стека, указав самый последний кадр внизу. Стрелка (
>
) указывает на текущий кадр, который определяет контекст большинства команд.
- d(own) [count]¶
Переместите текущее количество кадров (значение по умолчанию) на уровень ниже в трассировке стека (на более новый кадр).
- u(p) [count]¶
Переместите текущее количество кадров (по умолчанию) на более высокий уровень в трассировке стека (на более старый кадр).
- b(reak) [([filename:]lineno | function) [, condition]]¶
С помощью аргумента lineno установите разрыв в текущем файле. С помощью аргумента function установите разрыв в первом исполняемом операторе внутри этой функции. Перед номером строки может быть указано имя файла и двоеточие, чтобы указать точку останова в другом файле (возможно, в том, который еще не был загружен). Поиск файла выполняется по
sys.path
. Обратите внимание, что каждой точке останова присваивается номер, на который ссылаются все остальные команды точки останова.Если присутствует второй аргумент, то это выражение, значение которого должно быть равно true, прежде чем будет соблюдена точка останова.
Без аргументов перечислите все прерывания, в том числе для каждой точки останова, количество нажатий на эту точку останова, текущее количество игнорирований и соответствующее условие, если таковое имеется.
- tbreak [([filename:]lineno | function) [, condition]]¶
Временная точка останова, которая автоматически удаляется при первом нажатии. Аргументы те же, что и для
break
.
- cl(ear) [filename:lineno | bpnumber ...]¶
С аргументом filename:lineno удалите все точки останова в этой строке. В списке номеров точек останова, разделенных пробелом, удалите эти точки останова. Без аргумента удалите все точки останова (но сначала запросите подтверждение).
- disable [bpnumber ...]¶
Отключите точки останова, указанные в виде списка номеров точек останова, разделенных пробелом. Отключение точки останова означает, что она не может привести к остановке выполнения программы, но, в отличие от удаления точки останова, она остается в списке точек останова и может быть (повторно) включена.
- enable [bpnumber ...]¶
Включите указанные точки останова.
- ignore bpnumber [count]¶
Установите значение счетчика игнорирования для заданного номера точки останова. Если значение count опущено, значение счетчика игнорирования равно 0. Точка останова становится активной, когда значение счетчика игнорирования равно нулю. Если значение не равно нулю, значение count уменьшается при каждом достижении точки останова, и точка останова не отключается, а любое связанное с ней условие оценивается как true.
- condition bpnumber [condition]¶
Задайте новое условие для точки останова, выражение, значение которого должно быть равно true, прежде чем точка останова будет выполнена. Если условие отсутствует, все существующие условия удаляются; т.е. точка останова становится безусловной.
- commands [bpnumber]¶
Укажите список команд для номера точки останова bpnumber. Сами команды отображаются в следующих строках. Введите строку, содержащую только
end
, чтобы завершить выполнение команд. Пример:(Pdb) commands 1 (com) p 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) [lineno]¶
Без аргументов продолжайте выполнение до тех пор, пока не будет достигнута строка с номером, большим текущего.
Используя lineno, продолжайте выполнение до тех пор, пока не будет достигнута строка с номером, большим или равным lineno. В обоих случаях также остановитесь, когда вернется текущий кадр.
Изменено в версии 3.2: Разрешите указать явный номер строки.
- r(eturn)¶
Продолжайте выполнение до тех пор, пока не вернется текущая функция.
- c(ont(inue))¶
Продолжайте выполнение, останавливаясь только при достижении точки останова.
- j(ump) lineno¶
Укажите следующую строку, которая будет выполнена. Доступно только в самом нижнем фрейме. Это позволяет вам вернуться назад и выполнить код еще раз или перейти вперед, чтобы пропустить код, который вы не хотите запускать.
Следует отметить, что не все переходы разрешены - например, невозможно перейти в середину цикла
for
или выйти из предложенияfinally
.
- l(ist) [first[, last]]¶
Перечислите исходный код текущего файла. Без аргументов перечислите 11 строк вокруг текущей строки или продолжайте предыдущий список. С
.
В качестве аргумента перечислите 11 строк вокруг текущей строки. С одним аргументом перечислите 11 строк вокруг этой строки. Используя два аргумента, укажите заданный диапазон; если второй аргумент меньше первого, он интерпретируется как количество.Текущая строка в текущем кадре обозначается символом
->
. Если выполняется отладка исключения, строка, в которой первоначально возникло или распространилось исключение, обозначается символом>>
, если она отличается от текущей строки.Изменено в версии 3.2: Добавлен маркер
>>
.
- ll | longlist¶
Укажите весь исходный код для текущей функции или фрейма. Интересные строки помечены как
list
.Добавлено в версии 3.2.
- a(rgs)¶
Выведите аргументы текущей функции и их текущие значения.
- p expression¶
Вычислите выражение в текущем контексте и выведите его значение.
Примечание
print()
также может использоваться, но не является командой отладчика — она выполняет функцию Pythonprint()
.
- pp expression¶
Аналогично команде
p
, за исключением того, что значение expression выводится красивым шрифтом с помощью модуляpprint
.
- whatis expression¶
Выведите тип выражения.
- source expression¶
Попробуйте получить исходный код expression и отобразить его.
Добавлено в версии 3.2.
- display [expression]¶
Отображать значение выражения, если оно изменилось, каждый раз, когда выполнение останавливается в текущем кадре.
Без expression перечислите все отображаемые выражения для текущего кадра.
Примечание
Дисплей вычисляет expression и сравнивает с результатом предыдущей оценки expression, поэтому, если результат может быть изменен, дисплей может быть не в состоянии распознать изменения.
Пример:
lst = [] breakpoint() pass lst.append(1) print(lst)
Дисплей не распознает, что
lst
был изменен, поскольку результат оценки был изменен наlst.append(1)
перед сравнением:> example.py(3)<module>() -> pass (Pdb) display lst display lst: [] (Pdb) n > example.py(4)<module>() -> lst.append(1) (Pdb) n > example.py(5)<module>() -> print(lst) (Pdb)
Вы можете проделать несколько трюков с механизмом копирования, чтобы заставить его работать:
> example.py(3)<module>() -> pass (Pdb) display lst[:] display lst[:]: [] (Pdb) n > example.py(4)<module>() -> lst.append(1) (Pdb) n > example.py(5)<module>() -> print(lst) display lst[:]: [1] [old: []] (Pdb)
Добавлено в версии 3.2.
- undisplay [expression]¶
Больше не отображайте expression в текущем кадре. Без expression очистите все отображаемые выражения для текущего кадра.
Добавлено в версии 3.2.
- interact¶
Запустите интерактивный интерпретатор (используя модуль
code
), глобальное пространство имен которого содержит все (глобальные и локальные) имена, найденные в текущей области.Добавлено в версии 3.2.
- alias [name [command]]¶
Создайте псевдоним с именем name, который выполняет команду. Команда * не должна * заключаться в кавычки. Заменяемые параметры могут быть указаны как
%1
,%2
, и так далее, при этом%*
заменяется на все параметры. Если command опущен, отображается текущий псевдоним для name. Если аргументы не указаны, будут перечислены все псевдонимы.Псевдонимы могут быть вложенными и содержать все, что может быть легально введено в командной строке pdb. Обратите внимание, что внутренние команды pdb *могут быть заменены псевдонимами. Затем такая команда скрывается до тех пор, пока псевдоним не будет удален. Сглаживание рекурсивно применяется к первому слову командной строки; все остальные слова в строке остаются в покое.
В качестве примера приведем два полезных псевдонима (особенно при размещении в файле
.pdbrc
).:# Print instance variables (usage "pi classInst") alias pi for k in %1.__dict__.keys(): print(f"%1.{k} = {%1.__dict__[k]}") # Print instance variables in self alias ps pi self
- unalias name¶
Удалите указанный псевдоним name.
- ! statement¶
Выполните инструкцию (состоящую из одной строки) * в контексте текущего стекового фрейма. Восклицательный знак может быть опущен, если только первое слово инструкции не напоминает команду отладчика. Чтобы задать глобальную переменную, вы можете добавить к команде присваивания оператор
global
в той же строке, например:(Pdb) global list_options; list_options = ['-l'] (Pdb)
- run [args ...]¶
- restart [args ...]¶
Перезапустите программу отладчика на Python. Если указан параметр args, он разделяется на
shlex
, а результат используется как новыйsys.argv
. История, точки останова, действия и параметры отладчика сохраняются.restart
- это псевдоним дляrun
.
- q(uit)¶
Завершите работу с отладчиком. Выполняемая программа будет прервана.
- debug code¶
Введите рекурсивный отладчик, который выполняет пошаговое выполнение кода (который представляет собой произвольное выражение или инструкцию, выполняемую в текущей среде).
- retval¶
Выведите возвращаемое значение для последнего возврата текущей функции.
Сноски