You are currently viewing Ошибки и отладка

Ошибки и отладка

Разработка кода и анализ данных всегда требуют немного проб и ошибок, и 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 принимает один аргумент, режим, и есть три возможности: PlainContext, и 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 онлайн-документацией.