Разработка кода и анализ данных всегда требуют немного проб и ошибок, и IPython содержит инструменты для оптимизации этого процесса. В этом разделе будут кратко рассмотрены некоторые параметры управления отчетами об исключениях Python, а затем рассмотрены инструменты для отладки ошибок в коде.
Контрольные Исключения: %xmode
В большинстве случаев, когда сценарий Python завершается неудачно, он вызывает исключение. Когда интерпретатор сталкивается с одним из этих исключений, информацию о причине ошибки можно найти в обратной трассировке, доступ к которой можно получить из Python. С %xmode
помощью функции magic IPython позволяет управлять объемом информации, выводимой при возникновении исключения. Рассмотрим следующий код: В [1]:
def func1(a, b):
return a / b
def func2(x):
a = x
b = x - 1
return func1(a, b)
В [2]:
func2(1)
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
<ipython-input-2-b2e110f6fc8f> in <module>()
----> 1 func2(1)
<ipython-input-1-d849e34d61fb> in func2(x)
5 a = x
6 b = x - 1
----> 7 return func1(a, b)
<ipython-input-1-d849e34d61fb> in func1(a, b)
1 def func1(a, b):
----> 2 return a / b
3
4 def func2(x):
5 a = x
ZeroDivisionError: division by zero
Вызов func2
приводит к ошибке, а чтение распечатанной трассировки позволяет нам точно увидеть, что произошло. По умолчанию эта трассировка включает несколько строк, показывающих контекст каждого шага, приведшего к ошибке. Используя %xmode
волшебную функцию (сокращение от режима исключения), мы можем изменить то, какая информация печатается.
%xmode
принимает один аргумент, режим, и есть три возможности: Plain
, Context
, и Verbose
. Значение по умолчанию равно Context
, и выдает результат, подобный тому, который только что был показан ранее. Plain
является более компактным и дает меньше информации: В [3]:
%xmode Plain
Exception reporting mode: Plain
В [4]:
func2(1)
Traceback (most recent call last):
File "<ipython-input-4-b2e110f6fc8f>", line 1, in <module>
func2(1)
File "<ipython-input-1-d849e34d61fb>", line 7, in func2
return func1(a, b)
File "<ipython-input-1-d849e34d61fb>", line 2, in func1
return a / b
ZeroDivisionError: division by zero
Verbose
Режим добавляет некоторую дополнительную информацию, включая аргументы для любых вызываемых функций:
В [5]:
%xmode Verbose
Exception reporting mode: Verbose
В [6]:
func2(1)
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
<ipython-input-6-b2e110f6fc8f> in <module>()
----> 1 func2(1)
global func2 = <function func2 at 0x103729320>
<ipython-input-1-d849e34d61fb> in func2(x=1)
5 a = x
6 b = x - 1
----> 7 return func1(a, b)
global func1 = <function func1 at 0x1037294d0>
a = 1
b = 0
<ipython-input-1-d849e34d61fb> in func1(a=1, b=0)
1 def func1(a, b):
----> 2 return a / b
a = 1
b = 0
3
4 def func2(x):
5 a = x
ZeroDivisionError: division by zero
Эта дополнительная информация может помочь сузить круг причин возникновения исключения. Так почему бы не использовать этот Verbose
режим все время? По мере усложнения кода такой способ отслеживания может быть чрезвычайно длительным. В зависимости от контекста, иногда с краткостью Default
режима легче работать.
Отладка: При чтении обратных трассировок недостаточно
Стандартным инструментом Python для интерактивной отладки является pdb
отладчик Python. Этот отладчик позволяет пользователю пошагово просматривать код построчно, чтобы увидеть, что может быть причиной более сложной ошибки. Улучшенная версия IPython-это ipdb
отладчик IPython.
Существует множество способов запуска и использования обоих этих отладчиков; мы не будем здесь описывать их полностью. Дополнительные сведения см. в интерактивной документации этих двух утилит.
В IPython, пожалуй, самым удобным интерфейсом для отладки является команда %debug
magic. Если вы вызовете его после попадания в исключение, он автоматически откроет интерактивное приглашение для отладки в месте возникновения исключения. ipdb
Приглашение позволяет вам изучить текущее состояние стека, изучить доступные переменные и даже выполнить команды Python!
Давайте рассмотрим самое последнее исключение, затем выполните некоторые основные задачи–выведите значения a
и b
и введите quit
, чтобы завершить сеанс отладки:В [7]:
%debug
> <ipython-input-1-d849e34d61fb>(2)func1()
1 def func1(a, b):
----> 2 return a / b
3
ipdb> print(a)
1
ipdb> print(b)
0
ipdb> quit
Однако интерактивный отладчик позволяет гораздо больше, чем это–мы даже можем перемещаться вверх и вниз по стеку и изучать значения переменных там: В [8]:
%debug
> <ipython-input-1-d849e34d61fb>(2)func1()
1 def func1(a, b):
----> 2 return a / b
3
ipdb> up
> <ipython-input-1-d849e34d61fb>(7)func2()
5 a = x
6 b = x - 1
----> 7 return func1(a, b)
ipdb> print(x)
1
ipdb> up
> <ipython-input-6-b2e110f6fc8f>(1)<module>()
----> 1 func2(1)
ipdb> down
> <ipython-input-1-d849e34d61fb>(7)func2()
5 a = x
6 b = x - 1
----> 7 return func1(a, b)
ipdb> quit
Это позволяет быстро выяснить не только причину ошибки, но и то, какие вызовы функций привели к ошибке.
Если вы хотите, чтобы отладчик запускался автоматически при возникновении исключения, вы можете использовать функцию %pdb
magic, чтобы включить это автоматическое поведение: В [9]:
%xmode Plain
%pdb on
func2(1)
Exception reporting mode: Plain
Automatic pdb calling has been turned ON
Traceback (most recent call last):
File "<ipython-input-9-569a67d2d312>", line 3, in <module>
func2(1)
File "<ipython-input-1-d849e34d61fb>", line 7, in func2
return func1(a, b)
File "<ipython-input-1-d849e34d61fb>", line 2, in func1
return a / b
ZeroDivisionError: division by zero
> <ipython-input-1-d849e34d61fb>(2)func1()
1 def func1(a, b):
----> 2 return a / b
3
ipdb> print(b)
0
ipdb> quit
Наконец, если у вас есть сценарий, который вы хотели бы запустить с самого начала в интерактивном режиме , вы можете запустить его с %run -d
помощью команды и использовать next
ее для интерактивного просмотра строк кода.
Неполный список команд отладки
Существует гораздо больше доступных команд для интерактивной отладки, чем мы перечислили здесь; в следующей таблице приведено описание некоторых из наиболее распространенных и полезных команд:
Команда | Описание |
---|---|
list | Показать текущее местоположение в файле |
h(elp) | Покажите список команд или найдите справку по конкретной команде |
q(uit) | Выйдите из отладчика и программы |
c(ontinue) | Выйдите из отладчика, продолжите работу в программе |
n(ext) | Перейдите к следующему шагу программы |
<enter> | Повторите предыдущую команду |
p(rint) | Вывод переменных |
s(tep) | Войдите в подпрограмму |
r(eturn) | Возврат из подпрограммы |
Для получения дополнительной информации используйте help
команду в отладчике или ознакомьтесь с ipdb
онлайн-документацией.