Как использовать отладчик Python

Вступление

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

Отладчик Python предоставляет среду отладки для программ Python. Он поддерживает установку условных точек останова, пошаговое выполнение исходного кода по одной строке за раз, проверку стека и многое другое.

Интерактивная работа с отладчиком Python

Отладчик Python входит в состав стандартного дистрибутива Python в виде модуля + pdb +. Отладчик также является расширяемым и определяется как класс + Pdb +. Чтобы узнать больше, вы можете прочитать ofrial документацию + pdb +.

Мы начнем с работы с короткой программой, имеющей две глобальные variables, https: // www.digitalocean.com/community/tutorials/how-to-define-functions-in-python-3[function], которая создает вложенный https://www.digitalocean.com/community/tutorials/how-to-construct- for-loops-in-python-3 [loop] и конструкция + if name == 'main ': +, которая вызовет функцию + nested_loop () +.

looping.py

num_list = [500, 600, 700]
alpha_list = ['x', 'y', 'z']


def nested_loop():
   for number in num_list:
       print(number)
       for letter in alpha_list:
           print(letter)

if __name__ == '__main__':
   nested_loop()

Теперь мы можем запустить эту программу через отладчик Python, используя следующую команду:

python -m pdb looping.py

Флаг командной строки + -m + импортирует любой модуль Python для вас и запускает его как скрипт. В этом случае мы импортируем и запускаем модуль + pdb +, который передаем в команду, как показано выше.

После выполнения этой команды вы получите следующий вывод:

Output> /Users/sammy/looping.py(1)<module>()
-> num_list = [500, 600, 700]
(Pdb)

В выводе первая строка содержит текущее имя модуля (как указано с помощью + <module> +) с путем к каталогу, и напечатанный номер строки, который следует (в данном случае это + 1 +, но если есть это комментарий или другая неисполняемая строка, это может быть большее число). Вторая строка показывает текущую строку исходного кода, которая выполняется здесь, поскольку + pdb + предоставляет интерактивную консоль для отладки. Вы можете использовать команду + help +, чтобы узнать ее команды, и + help +, чтобы узнать больше о конкретной команде. Обратите внимание, что консоль + pdb + отличается от интерактивной оболочки Python.

Отладчик Python автоматически запустится заново, когда достигнет конца вашей программы. Всякий раз, когда вы хотите покинуть консоль + pdb, введите команду` + quit` или + exit. Если вы хотите явно перезапустить программу в любом месте программы, вы можете сделать это с помощью команды + run +.

Использование отладчика для перемещения по программе

При работе с программами в отладчике Python вы, скорее всего, будете использовать команды + list,` + step` и + next для перемещения по своему коду. Мы рассмотрим эти команды в этом разделе.

Внутри оболочки мы можем набрать команду + list, чтобы получить контекст вокруг текущей строки. Из первой строки программы + looping.py +, которую мы отобразили выше - + num_list = [500, 600, 700] + -, это будет выглядеть так:

(Pdb)
 1  -> num_list = [500, 600, 700]
 2     alpha_list = ['x', 'y', 'z']
 3
 4
 5     def nested_loop():
 6         for number in num_list:
 7             print(number)
 8             for letter in alpha_list:
 9                 print(letter)
10
11     if __name__ == '__main__':
(Pdb)

Текущая строка обозначается символами + → +, которая в нашем случае является первой строкой файла программы.

Поскольку это относительно короткая программа, мы получаем почти всю программу обратно с помощью команды + list +. Без предоставления аргументов команда + list + предоставляет 11 строк вокруг текущей строки, но вы также можете указать, какие строки включить, например:

(Pdb)
 3
 4
 5     def nested_loop():
 6         for number in num_list:
 7             print(number)
(Pdb)

Здесь мы просили, чтобы строки 3-7 отображались с помощью команды + list 3, 7 +.

Чтобы перемещаться по программе построчно, мы можем использовать + step или` + next`:

(Pdb)
> /Users/sammy/looping.py(2)<module>()
-> alpha_list = ['x', 'y', 'z']
(Pdb)
(Pdb)
> /Users/sammy/looping.py(2)<module>()
-> alpha_list = ['x', 'y', 'z']
(Pdb)

Разница между + step + и + next + в том, что + step + остановится в вызываемой функции, в то время как + next + выполняет вызванные функции, чтобы останавливаться только на следующей строке текущей функции. Мы видим эту разницу, когда работаем с функцией.

Команда + step + будет перебирать циклы, как только доберется до выполнения функции, показывая, что именно делает цикл, поскольку сначала она напечатает число с помощью + print (number) +, а затем выполнит печать буквы с + print (letter) +, вернутся к числу и т.д .:

(Pdb)
> /Users/sammy/looping.py(5)<module>()
-> def nested_loop():
(Pdb)
> /Users/sammy/looping.py(11)<module>()
-> if __name__ == '__main__':
(Pdb)
> /Users/sammy/looping.py(12)<module>()
-> nested_loop()
(Pdb)
--Call--
> /Users/sammy/looping.py(5)nested_loop()
-> def nested_loop():
(Pdb)
> /Users/sammy/looping.py(6)nested_loop()
-> for number in num_list:
(Pdb)
> /Users/sammy/looping.py(7)nested_loop()
-> print(number)
(Pdb)
500
> /Users/sammy/looping.py(8)nested_loop()
-> for letter in alpha_list:
(Pdb)
> /Users/sammy/looping.py(9)nested_loop()
-> print(letter)
(Pdb)
x
> /Users/sammy/looping.py(8)nested_loop()
-> for letter in alpha_list:
(Pdb)
> /Users/sammy/looping.py(9)nested_loop()
-> print(letter)
(Pdb)
y
> /Users/sammy/looping.py(8)nested_loop()
-> for letter in alpha_list:
(Pdb)

Команда + next +, вместо этого, выполнит всю функцию, не показывая пошаговый процесс. Давайте выйдем из текущего сеанса с помощью команды + exit + и затем снова запустим отладчик:

python -m pdb looping.py

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

(Pdb)
> /Users/sammy/looping.py(5)<module>()
-> def nested_loop():
(Pdb)
> /Users/sammy/looping.py(11)<module>()
-> if __name__ == '__main__':
(Pdb)
> /Users/sammy/looping.py(12)<module>()
-> nested_loop()
(Pdb)
500
x
y
z
600
x
y
z
700
x
y
z
--Return--
> /Users/sammy/looping.py(12)<module>()->None
-> nested_loop()
(Pdb)

Проходя по своему коду, вы можете захотеть проверить значение, переданное переменной, что вы можете сделать с помощью команды + pp +, которая автоматически напечатает значение выражения, используя https: //docs.python. org / 3 / library / pprint.html # module-pprint [+ pprint + module]:

(Pdb)
[500, 600, 700]
(Pdb)

Большинство команд в + pdb + имеют более короткие псевдонимы. Для + step + эта краткая форма - + s +, а для + next + - + n +. Команда + help + выведет список доступных псевдонимов. Вы также можете вызвать последнюю команду, которую вы вызвали, нажав клавишу + ENTER + в приглашении.

Контрольные точки

Как правило, вы будете работать с более крупными программами, чем в приведенном выше примере, поэтому вам, скорее всего, захочется взглянуть на определенные функции или строки, а не просматривать всю программу. Используя команду + break + для установки точек останова, вы запустите программу до указанной точки останова.

Когда вы вставляете точку останова, отладчик назначает ей номер. Числа, назначенные точкам останова, являются последовательными целыми числами, которые начинаются с цифры 1, на которую вы можете ссылаться при работе с точками останова.

Точки останова могут быть размещены на определенных номерах строк, следуя синтаксису + <номер_программы>: <номер_строки> +, как показано ниже:

(Pdb)
Breakpoint 1 at /Users/sammy/looping.py:5
(Pdb)

Введите + clear + и затем + y +, чтобы удалить все текущие точки останова. Затем вы можете разместить точку останова там, где определена функция:

(Pdb)
Breakpoint 1 at /Users/sammy/looping.py:5
(Pdb)

Чтобы удалить текущие точки останова, введите + clear + и затем + y +. Вы также можете настроить условие:

(Pdb)
Breakpoint 1 at /Users/sammy/looping.py:7
(Pdb)

Теперь, если мы введем команду + continue +, программа прервется, когда значение + number + + x + будет оценено как больше 500 (то есть, когда оно будет установлено равным 600 во второй итерации внешний цикл):

(Pdb)
500
x
y
z
> /Users/sammy/looping.py(7)nested_loop()
-> print(number)
(Pdb)

Чтобы увидеть список точек останова, которые в данный момент настроены на запуск, используйте команду + break + без каких-либо аргументов. Вы получите информацию об особенностях установленных вами точек останова:

(Pdb)
Num Type         Disp Enb   Where
1   breakpoint   keep yes   at /Users/sammy/looping.py:7
   stop only if number > 500
   breakpoint already hit 2 times
(Pdb)

Мы также можем отключить точку останова командой + disable + и номером точки останова. В этом сеансе мы добавляем еще одну точку останова, а затем отключаем первую:

(Pdb)
Breakpoint 2 at /Users/sammy/looping.py:11
(Pdb)
Disabled breakpoint 1 at /Users/sammy/looping.py:7
(Pdb)
Num Type         Disp Enb   Where
1   breakpoint   keep     at /Users/sammy/looping.py:7
   stop only if number > 500
   breakpoint already hit 2 times
2   breakpoint   keep    at /Users/sammy/looping.py:11
(Pdb)

Чтобы включить точку останова, используйте команду + enable +, а для полного удаления точки останова используйте команду + clear +:

(Pdb) enable 1
Enabled breakpoint 1 at /Users/sammy/looping.py:7
(Pdb) clear 2
Deleted breakpoint 2 at /Users/sammy/looping.py:11
(Pdb)

Точки останова в + pdb + дают вам много контроля. Некоторые дополнительные функции включают в себя игнорирование точек останова во время текущей итерации программы с помощью команды + ignore + (как в + ignore 1 +), запуск действий на точке останова с помощью команды + commands + (как в + команда 1 + `) и создание временных точек останова, которые автоматически очищаются при первом попадании программы в точку с помощью команды + tbreak + (например, для временного прерывания в строке 3 вы можете набрать + tbreak 3 + ` ).

Интеграция + pdb + в программы

Вы можете запустить сеанс отладки, импортировав модуль + pdb + и добавив функцию + pdb + + pdb.set_trace () + над строкой, в которой вы хотите начать сеанс.

В нашем примере программы мы добавим оператор + import + и функцию, в которую мы хотим войти в отладчик. Для нашего примера давайте добавим его перед вложенным циклом.

# Import pdb module
import pdb

num_list = [500, 600, 700]
alpha_list = ['x', 'y', 'z']


def nested_loop():
   for number in num_list:
       print(number)

       # Trigger debugger at this line
       pdb.set_trace()
       for letter in alpha_list:
           print(letter)

if __name__ == '__main__':
   nested_loop()

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

Импорт модуля + pdb + и запуск функции + pdb.set_trace () + позволяет вам запустить вашу программу как обычно и запустить отладчик во время ее выполнения.

Модификация потока выполнения программы

Отладчик Python позволяет вам изменять поток вашей программы во время выполнения с помощью команды + jump +. Это позволяет вам пропустить вперед, чтобы предотвратить запуск некоторого кода, или может позволить вам вернуться назад, чтобы снова запустить код.

Мы будем работать с небольшой программой, которая создает список букв, содержащихся в строке + sammy =" sammy "+:

letter_list.py

def print_sammy():
   sammy_list = []
   sammy = "sammy"
   for letter in sammy:
       sammy_list.append(letter)
       print(sammy_list)

if __name__ == "__main__":
   print_sammy()

Если мы запустим программу как обычно с помощью команды + python letter_list.py +, мы получим следующий вывод:

Output['s']
['s', 'a']
['s', 'a', 'm']
['s', 'a', 'm', 'm']
['s', 'a', 'm', 'm', 'y']

С отладчиком Python, давайте покажем, как мы можем изменить выполнение, сначала * прыгнув вперед * после первого цикла. Когда мы сделаем это, мы заметим, что происходит нарушение https://www.digitalocean.com/community/tutorials/how-to-construct-for-loops-in-python-3 [+ for + цикл]:

python -m pdb letter_list.py
> /Users/sammy/letter_list.py(1)<module>()
-> def print_sammy():
(Pdb)
 1  -> def print_sammy():
 2         sammy_list = []
 3         sammy = "sammy"
 4         for letter in sammy:
 5             sammy_list.append(letter)
 6             print(sammy_list)
 7
 8     if __name__ == "__main__":
 9         print_sammy()
10
11
(Pdb)
Breakpoint 1 at /Users/sammy/letter_list.py:5
(Pdb)
> /Users/sammy/letter_list.py(5)print_sammy()
-> sammy_list.append(letter)
(Pdb)
's'
(Pdb)
['s']
> /Users/sammy/letter_list.py(5)print_sammy()
-> sammy_list.append(letter)
(Pdb)
> /Users/sammy/letter_list.py(6)print_sammy()
-> print(sammy_list)
(Pdb)
'a'
(Pdb)
Disabled breakpoint 1 at /Users/sammy/letter_list.py:5
(Pdb)
['s']
['s', 'm']
['s', 'm', 'm']
['s', 'm', 'm', 'y']

Вышеупомянутый сеанс отладки помещает разрыв в строку 5, чтобы предотвратить продолжение кода, а затем продолжается через код (наряду с симпатичной печатью некоторых значений + letter +, чтобы показать, что происходит). Далее мы используем команду + jump +, чтобы перейти к строке 6. В этот момент переменная + letter + устанавливается равной строке + 'a' +, но мы переходим к коду, который добавляет это в список + sammy_list +. Затем мы отключаем точку останова, чтобы продолжить выполнение как обычно с помощью команды + continue +, поэтому + 'a' + никогда не добавляется к + sammy_list +.

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

> /Users/sammy/letter_list.py(1)<module>()
-> def print_sammy():
(Pdb)
 1  -> def print_sammy():
 2         sammy_list = []
 3         sammy = "sammy"
 4         for letter in sammy:
 5             sammy_list.append(letter)
 6             print(sammy_list)
 7
 8     if __name__ == "__main__":
 9         print_sammy()
10
11
(Pdb)
Breakpoint 1 at /Users/sammy/letter_list.py:6
(Pdb)
> /Users/sammy/letter_list.py(6)print_sammy()
-> print(sammy_list)
(Pdb)
's'
(Pdb)
> /Users/sammy/letter_list.py(5)print_sammy()
-> sammy_list.append(letter)
(Pdb)
> /Users/sammy/letter_list.py(6)print_sammy()
-> print(sammy_list)
(Pdb)
's'
(Pdb)
Disabled breakpoint 1 at /Users/sammy/letter_list.py:6
(Pdb)
['s', 's']
['s', 's', 'a']
['s', 's', 'a', 'm']
['s', 's', 'a', 'm', 'm']
['s', 's', 'a', 'm', 'm', 'y']

В приведенном выше сеансе отладки мы добавили разрыв в строке 6, а затем после продолжения вернулись к строке 5. По пути мы красиво напечатали, чтобы показать, что строка + 's' + была добавлена ​​в список + sammy_list + дважды. Затем мы отключили разрыв в строке 6 и продолжили выполнение программы. Выходные данные показывают два значения + 's' +, добавленные к + sammy_list +.

Некоторые переходы предотвращаются отладчиком, особенно при переходе в определенные операторы управления потоком, которые не определены. Например, вы не можете перейти к функциям до определения аргументов, и вы не можете перейти к середине оператора + try: кроме +. Вы также не можете выпрыгнуть из блока + finally +.

Оператор + jump + с отладчиком Python позволяет вам изменять поток выполнения при отладке программы, чтобы увидеть, можно ли изменить управление потоком для различных целей или чтобы лучше понять, какие проблемы возникают в вашем коде.

Таблица общих команд + pdb +

Вот таблица полезных команд + pdb + вместе с их краткими формами, которые следует учитывать при работе с отладчиком Python.

Command Short form What it does

args

a

Print the argument list of the current function

break

b

Creates a breakpoint (requires parameters) in the program execution

continue

c or cont

Continues program execution

help

h

Provides list of commands or help for a specified command

jump

j

Set the next line to be executed

list

l

Print the source code around the current line

next

n

Continue execution until the next line in the current function is reached or returns

step

s

Execute the current line, stopping at first possible occasion

pp

pp

Pretty-prints the value of the expression

quit or exit

q

Aborts the program

return

r

Continue execution until the current function returns

Вы можете прочитать больше о командах и работе с отладчиком в документации по отладчику Python.

Заключение

Отладка - важный шаг любого проекта по разработке программного обеспечения. Отладчик Python + pdb + реализует интерактивную среду отладки, которую вы можете использовать с любой из ваших программ, написанных на Python.

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