Найти в Дзене
@coolcoders

Отладка python с помощью pdb

Оглавление

Представьте, что у вас нет редактора кода. Только консоль. И код вы пишете с помощью консольных текстовых редакторов. Ну, или вы просто презираете GUI. В таком случае на помощь приходит встроенный модуль для откладки в python - PDB

Использование отладчика

Создадим простой код

1_example.py

def hello(name):
return "hello " + name

if __name__ == "__main__":
hello(name)

Этот код выдает ошибку:

Traceback (most recent call last):
File "C:\Users\User\Desktop\1_example.py", line 5, in <module>
hello(name)
NameError: name 'name' is not defined

Предположим, что мы тупые и не понимаем почему возникла эта ошибка. В таком случае запустим отладчик

Чтобы запустить отладчик, пишем -m pdb перед название файла

python -m pdb 1_example.py

И увидим вот такой вывод:

> ...\1_example.py(1)<module>()
-> def hello(name):
(Pdb) >
  • 1 строка показывает где мы сейчас находимся
  • 2 строка показывает какая строка будет выполняться следующей
  • 3 строка дает нам ввести команды

Команды pdb

help(h)

Вызывает окно помощи:

-2

Также можно посмотреть описание каждой команды:

-3

quit(q) / exit

Позволяеют выйти из отладчика:

-4

Команды передвижения

next(n)

Переходит к выполнению следующей линии:

-5

Кстати, pdb запоминает последнюю команду, так что вы можете просто нажимать пробел и он повтрит последнюю команду

step(s)

То же, что и next, но он будет заходить в функции, циклы, условия и т. д.

Для этого примера давайте поправим наш код:

def hello(name):
return "hello " + name
if __name__ == "__main__":
name = "Alex"
hello(name)
-6

until(unt)

Повзволяет перейти к следующей строке кода, но гарантировано чтобы номер строки был больше чем текущий. Пример: если вы находитесь в конце тела цикла, но это не последняя итерация, то вас не отправит в начало тела цикла, а выполнится весь цикл и отладчик встанет на следующей строке после цикла, в отличии от next или step

Для этого примера возьмем другой код

2_example.py

for i in range(10):
print(i)

print("End")
-7

down(d) / up(u)

Позволяют передвигаться по стэк-фрейму до нового и старого фрейма:

-8

Просмотр кода

list(l)

Выводит 10 строк(или меньше, если код меньше) по 5 над и под строкой действия. Но в любом случае должно вывестись 10 строчек кода:

-9

EOF означает, что там больше нечего выводить

Также может выводить срез:

-10

Кстати стрелкой(- >) показывает строку, где мы сейчас находимся

longlist(ll)

Выводит весь код:

-11

where(w)

Показывает наше текущее место в коде:

-12

source

Позволяет просматривать исходный код объекта: функция, класс и т. д.:

-13

Создание команд

alias

Позволяет создать свою команду:

-14

Также написав alias вы можете узнать созданные вами команды

unalias

Удаляет созданную команду:

-15

Рестарт кода

run / restart

Перезагружают скрипт с заданными параметрами:

-16

Команды вывода

args(a)

Позволяет узнать аргументы функций:

-17

p

Работает как print():

-18

pp

PreatyPrint, работате как pprint()

Для этого пример возьмем другой код

3_example.py

dictt = {'names': ["Alex", "Olivia", "Posie"], "surnames": ["Beridze", "Tsiklauri", "Bolkvadze"]}
-19

return(r)

Завершает текущую функцию

retval(rv)

Возвращает значение функции:

-20

whatis

Выводит тип объекта:

-21

display

Позволяет выводить значение одного аругмента каждый шаг. Это может быть полезно в циклах:

-22

undisplay

Убирает аргумент из display

Выполнение кода

!-префикс

Позволяет выполнять любой однострочный код:

-23

Причем этот код влияет на скрипт

interact

Вызывает python-интерпретатор:

-24

Чтобы выйти из него введите exit()

Код в интерпретаторе не влияет на скрипт

Точки останова

Теперь мы подошли к самому главному. Точки останова, или же breakpoints. Они нужны, чтобы мы могли переходить по разным кусочкам кода

break(b)

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

-25

Мы установили breakpoint на строке 5

Чтобы сразу перейти к нему, используем команду continue

Кстати наш breakpoint сообщает сколько раз мы его вызывали:

-26

continue(cont(c))

Позволяет двигаться по коду и останавливаться на точках останова:

-27

clear(cl)

Удаляет все или 1 breakpoint:

-28

Как вы могли заметить номер точки останова не меняется, даже после удаления предыдущей

enable / disable

Включает и выключает определенный breakpoint

commands

Позволяет выполнять какую-либо команду после перехода на breakpoint:

-29

tbreak

Создает временный breakpoint, который удаляется после первого использования

ignore

Игнорировать какое-то количество раз определнный breakpoint:

-30

jump(j)

Позволяет прыгнуть на определенную строку кода:

-31

breakpoint в коде

Вы легко можете запустить режим отладки, если в коде напишите строку:

import pdb; pdb.set_trace()

Пример:

def hello(name):
return "hello " + name

if __name__ == "__main__":
import pdb; pdb.set_trace()
name = "Alex"
hello(name)

В таком случае нам нужно запустить код без флага -m.

python 1_example.py

И мы снова попадем в отладчик pdb

Кстати, в версии Python 3.7 вместо import pdb; pdb.set_trace() можно использовать функцию breakpoint()

Заключение

Иточники:
оффициальная документация
Статья на real python
Еще одна небольшая статья на русском

Пост создан для тг-канала @coolcoders