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.

run(statement, globals=None, locals=None)
runeval(expression, globals=None, locals=None)
runcall(function, *args, **kwds)
set_trace()

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

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

Ниже перечислены команды, распознанные отладчиком. Большинство команд могут быть сокращены до одной или двух букв, как указано; например, 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() также может использоваться, но не является командой отладчика — она выполняет функцию Python print().

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

Выведите возвращаемое значение для последнего возврата текущей функции.

Сноски

Вернуться на верх