Меню

Integer division or modulo by zero python ошибка

ZeroDivisionError occurs when a number is divided by a zero. In Mathematics, when a number is divided by a zero, the result is an infinite number. It is impossible to write an Infinite number physically. Python interpreter throws “ZeroDivisionError: division by zero” error if the result is infinite number.

You can divide a number by another number. The division operation divides a number into equal parts or groups. Dividing a number into zero pieces or zero groups is meaning less. In mathematics, dividing a number by zero is undefined.

If a number is divided by zero, the result wil be infinite number. Python can not handle the infinite number because the infinite number is difficult to write in concrete form. In this case, Python throws “ZeroDivisionError: division by zero”. The error would be thrown as like below.

Traceback (most recent call last):
  File "/Users/python/Desktop/test.py", line 3, in <module>
    c=a/b;
ZeroDivisionError: integer division or modulo by zero
[Finished in 0.1s with exit code 1]

Different Variation of the error

In different contexts the Zero Division Error-division by zero is thrown in various forms in python. The numerous variations of ZeroDivisionError are given below.

ZeroDivisionError: integer division or modulo by zero
ZeroDivisionError: long division or modulo by zero
ZeroDivisionError: float division by zero
ZeroDivisionError: complex division by zero
ZeroDivisionError: division by zero

Root Cause

The zero division error is due to either a number being divided by zero, or a number being modulo by zero. The denominator of the division operation should be a non zero numeric value. If the demonimator is zero then ZeroDivisionError will be thrown by python interpreter.

Dividing a number into zero pieces or zero groups does not make sense. The result is infinite number not representable in python. Therefore, python throws “ZeroDivisionError: integer division or modulo by zero”. This error occurs for all numbers such as integer, long, float and complex number

How to reproduce this issue

A number must be divided by an another non zero number. Python interpreter will throw ZeroDivisionError if you create a simple program with a number divided by zero. If the division denominator is set to zero, then this error will occur.

The example code below shows how this issue can be reproduced.

a = 8
b = 0
c = a / b
print c

Output

Traceback (most recent call last):
  File "C:UsersUserDesktoppython.py", line 3, in <module>
    c = a / b
ZeroDivisionError: division by zero
Traceback (most recent call last):
  File "/Users/python/Desktop/test.py", line 3, in <module>
    c = a / b
ZeroDivisionError: integer division or modulo by zero
[Finished in 0.0s with exit code 1]

Solution 1

Python can not divide a number by zero. Before doing a division or modulo operation, the denominator must be verified for nonzero. The code below shows how to handle a denominator when it is zero.

a = 8
b = 0
c = ( a / b ) if b != 0 else 0
print c

Output

0

Solution 2

If the program is not sure of the denominator value, the denominator value may be zero in some rare cases. In this case, handle the ZeroDivisionError when it occurs. The example below shows how to handle the exception of ZeroDivisionError in the code.

try:
	a = 8
	b = 0
	c = a / b
except ZeroDivisionError:
	c = 0
print c

Output

0

Solution 3

In the program, if the denominator is zero, the output of the division operation can be set to zero. Mathematically, this may not be correct. Setting zero for the division operation will solve this issue in real-time calculation. The following code shows how to set the zero for the division operation.

a = 8
b = 0
if b == 0:
	c = 0
else:
	c = a / b
print c

Output

0

Содержание

  1. Integer division or modulo by zero error
  2. ZeroDivisionError: division by zero in Python #
  3. ZeroDivisionError: division by zero
  4. Different Variation of the error
  5. Root Cause
  6. How to reproduce this issue
  7. Output
  8. Solution 1
  9. Output
  10. Solution 2
  11. Output
  12. Solution 3
  13. ZeroDivisionError: as ‘integer division or modulo by zero’ but get as ‘division by zero
  14. 2 Answers 2
  15. Обработка исключений в Python
  16. Основные исключения
  17. Как обрабатывать исключения?
  18. ZeroDivisionError: float division | Python
  19. ZeroDivisionError
  20. Handling ZeroDivisionError in Python
  21. Reproducing the error
  22. Output:
  23. Wrap it in try except
  24. Check before you do the division
  25. Different Variation

Integer division or modulo by zero error

The Python «ZeroDivisionError: integer division or modulo by zero» occurs when we use the modulo % operator with an integer and a zero.

To solve the error, figure out where the 0 comes from and correct the assignment.

Here is an example of how the error occurs.

We tried using the modulo % operator with a zero.

It’s unclear what value is expected when we divide by 0 , so Python throws an error.

When we divide a number by 0 , the result tends towards infinity.

Here are some unexpected sources of 0 .

If you use the random.randint() method or the range() class, make sure to start from 1 , and not from 0 .

You can also conditionally check if the variable doesn’t store a 0 value before using the modulo operator.

Alternatively, you can use a try/except statement.

We use the modulo operator and if we get a ZeroDivisionError , the except block is run.

You can set the result variable to a value that suits your use case in the except block or simply pass.

The modulo (%) operator returns the remainder from the division of the first value by the second.

If the value on the right-hand side is zero, the operator raises a ZeroDivisionError exception.

The left and right-hand side values may also be floating point numbers.

If the left-hand side value is a float and the right-hand side value is 0 , you would get a «ZeroDivisionError: float modulo» error.

ZeroDivisionError: division by zero in Python #

The Python «ZeroDivisionError: division by zero» occurs when we try to divide a number by 0 .

To solve the error, use an if statement to check if the number you are dividing by is not zero, or handle the error in a try/except block.

Here is an example of how the error occurs.

It’s unclear what value is expected when we divide by 0 , so Python throws an error.

When we divide a number by 0 , the result tends towards infinity.

One way to solve the error is to check if the value we are dividing by is not 0 .

We check if the b variable doesn’t store a 0 value and if it doesn’t, we divide a by b .

If setting the result variable to 0 , if b is equal to 0 suits your use case, you can shorten this to a single line.

The expression x and y first evaluates x , and if x is falsy, its value is returned, otherwise, y is returned.

Alternatively, you can use a try/except statement.

The try/except block is known as «asking for forgiveness, rather than permission».

We try to divide a by b and if we get a ZeroDivisionError , the except block sets the result variable to 0 .

The best way to solve the error is to figure out where the variable gets assigned a 0 and check whether that’s the expected behavior.

Here are some common ways you might get a zero value unexpectedly.

Источник

ZeroDivisionError: division by zero

ZeroDivisionError occurs when a number is divided by a zero. In Mathematics, when a number is divided by a zero, the result is an infinite number. It is impossible to write an Infinite number physically. Python interpreter throws “ZeroDivisionError: division by zero” error if the result is infinite number.

You can divide a number by another number. The division operation divides a number into equal parts or groups. Dividing a number into zero pieces or zero groups is meaning less. In mathematics, dividing a number by zero is undefined.

If a number is divided by zero, the result wil be infinite number. Python can not handle the infinite number because the infinite number is difficult to write in concrete form. In this case, Python throws “ZeroDivisionError: division by zero”. The error would be thrown as like below.

Different Variation of the error

In different contexts the Zero Division Error-division by zero is thrown in various forms in python. The numerous variations of ZeroDivisionError are given below.

Root Cause

The zero division error is due to either a number being divided by zero, or a number being modulo by zero. The denominator of the division operation should be a non zero numeric value. If the demonimator is zero then ZeroDivisionError will be thrown by python interpreter.

Dividing a number into zero pieces or zero groups does not make sense. The result is infinite number not representable in python. Therefore, python throws “ZeroDivisionError: integer division or modulo by zero”. This error occurs for all numbers such as integer, long, float and complex number

How to reproduce this issue

A number must be divided by an another non zero number. Python interpreter will throw ZeroDivisionError if you create a simple program with a number divided by zero. If the division denominator is set to zero, then this error will occur.

The example code below shows how this issue can be reproduced.

Output

Solution 1

Python can not divide a number by zero. Before doing a division or modulo operation, the denominator must be verified for nonzero. The code below shows how to handle a denominator when it is zero.

Output

Solution 2

If the program is not sure of the denominator value, the denominator value may be zero in some rare cases. In this case, handle the ZeroDivisionError when it occurs. The example below shows how to handle the exception of ZeroDivisionError in the code.

Output

Solution 3

In the program, if the denominator is zero, the output of the division operation can be set to zero. Mathematically, this may not be correct. Setting zero for the division operation will solve this issue in real-time calculation. The following code shows how to set the zero for the division operation.

Источник

ZeroDivisionError: as ‘integer division or modulo by zero’ but get as ‘division by zero

I want to get the exception of ZeroDivisionError: as ‘integer division or modulo by zero’, but I get as ‘division by zero’. How can I get that?

2 Answers 2

The Python exception is ZeroDivisionError :

If you are trying to handle the exception, do an:

instead of trying to match the exception description.

If this answer doesn’t cover you, please expand on what your needs are and why, so that we help you.

PS A naïve way to accomplish what you seem to ask:

I’m sure you have a reason for wanting the specific error message (maybe to understand float vs int division) so I’ll address that.

Even though there is only one divide by zero exception ( ZeroDivisionError ) it’s given with a different error message depending on the types used and the operation involved.

If you’re trying to get the integer division exception message ( «integer division or modulo by zero» ), you need to perform integer division specifically using // instead of / . Converting numbers to integers with int() before or after dividing doesn’t make / perform integer division.

As an example of how the error messages vary depending on the types involved:

The above pertains to Python 3. / division in Python 2 of two int objects where the denominator is zero would result in the «integer division or modulo by zero» message.

Источник

Обработка исключений в Python

Что вы предпринимаете, когда с работой вашей программы что-то идет не так? Допустим, вы пытаетесь открыть файл, но вы ввели неверный путь, или вы хотите узнать информацию у пользователей и они пишут какую-то бессмыслицу. Вы не хотите, чтобы ваша программа крэшилась, по-этому вы выполняете обработку исключений. В Пайтоне, конструкция всегда обернута в то, что называется try/except. В данном разделе мы рассмотрим следующие понятия:

  • Базовые типы исключений;
  • Обработка исключений при помощи try/except;
  • Узнаем, как работает try/except/finally;
  • Выясним, как работает оператор else совместно с try/except;

Начнем со знакомства с самыми обычными исключениями, которые вы увидите в Пайтоне. Обратите внимание на то, что ошибка и исключение – два разных слова, описывающие одно и то же, в контексте обработки исключений.

Основные исключения

Вы уже сталкивались со множеством исключений. Ниже изложен список основных встроенных исключений (определение в документации к Пайтону):

  • Exception – то, на чем фактически строятся все остальные ошибки;
  • AttributeError – возникает, когда ссылка атрибута или присвоение не могут быть выполнены;
  • IOError – возникает в том случае, когда операция I/O (такая как оператор вывода, встроенная функция open() или метод объекта-файла) не может быть выполнена, по связанной с I/O причине: «файл не найден», или «диск заполнен», иными словами.
  • ImportError – возникает, когда оператор import не может найти определение модуля, или когда оператор не может найти имя файла, который должен быть импортирован;
  • IndexError – возникает, когда индекс последовательности находится вне допустимого диапазона;
  • KeyError – возникает, когда ключ сопоставления (dictionary key) не найден в наборе существующих ключей;
  • KeyboardInterrupt – возникает, когда пользователь нажимает клавишу прерывания(обычно Delete или Ctrl+C);
  • NameError – возникает, когда локальное или глобальное имя не найдено;
  • OSError – возникает, когда функция получает связанную с системой ошибку;
  • SyntaxError — возникает, когда синтаксическая ошибка встречается синтаксическим анализатором;
  • TypeError – возникает, когда операция или функция применяется к объекту несоответствующего типа. Связанное значение представляет собой строку, в которой приводятся подробные сведения о несоответствии типов;
  • ValueError – возникает, когда встроенная операция или функция получают аргумент, тип которого правильный, но неправильно значение, и ситуация не может описано более точно, как при возникновении IndexError;
  • ZeroDivisionError – возникает, когда второй аргумент операции division или modulo равен нулю;

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

Как обрабатывать исключения?

Обработка исключений в Пайтон – это очень просто. Потратим немного времени и напишем несколько примеров, которые их вызовут. Мы начнем с одной из самых элементарных проблем: деление на ноль.

Источник

ZeroDivisionError: float division | Python

In mathematics, any non-zero number either positive or negative divided by zero is undefined because there is no value. The reason is that the result of a division by zero is undefined is the fact that any attempt at a definition leads to a contradiction.

ZeroDivisionError

The super class of ZeroDivisionError is ArithmeticError. ZeroDivisionError is a built-in Python exception thrown when a number is divided by 0. This means that the exception raised when the second argument of a division or modulo operation is zero. In Mathematics, when a number is divided by a zero, the result is an infinite number. It is impossible to write an Infinite number physically. Python interpreter throws «ZeroDivisionError» error if the result is infinite number. While implementing any program logic and there is division operation make sure always handle ArithmeticError or ZeroDivisionError so that program will not terminate.

Handling ZeroDivisionError in Python

The above code can be reduced to:

Reproducing the error

Output:

You can solve the ZeroDivisionError by the following ways:

Wrap it in try except

Check before you do the division

The above code can be reduced to:

Different Variation

In Python, the Zero Division Error:division by zero is thrown in various forms in different contexts. They are given below:

  1. ZeroDivisionError: division by zero
  2. ZeroDivisionError: float division by zero
  3. ZeroDivisionError: integer division or modulo by zero
  4. ZeroDivisionError: long division or modulo by zero
  5. ZeroDivisionError: complex division by zero

Источник

Что вы предпринимаете, когда с работой вашей программы что-то идет не так? Допустим, вы пытаетесь открыть файл, но вы ввели неверный путь, или вы хотите узнать информацию у пользователей и они пишут какую-то бессмыслицу. Вы не хотите, чтобы ваша программа крэшилась, по-этому вы выполняете обработку исключений. В Пайтоне, конструкция всегда обернута в то, что называется try/except. В данном разделе мы рассмотрим следующие понятия:

  • Базовые типы исключений;
  • Обработка исключений при помощи try/except;
  • Узнаем, как работает try/except/finally;
  • Выясним, как работает оператор else совместно с try/except;

Начнем со знакомства с самыми обычными исключениями, которые вы увидите в Пайтоне. Обратите внимание на то, что ошибка и исключение – два разных слова, описывающие одно и то же, в контексте обработки исключений.

Основные исключения

Вы уже сталкивались со множеством исключений. Ниже изложен список основных встроенных исключений (определение в документации к Пайтону):

  • Exception – то, на чем фактически строятся все остальные ошибки;
  • AttributeError – возникает, когда ссылка атрибута или присвоение не могут быть выполнены;
  • IOError – возникает в том случае, когда операция I/O (такая как оператор вывода, встроенная функция open() или метод объекта-файла) не может быть выполнена, по связанной с I/O причине: «файл не найден», или «диск заполнен», иными словами.
  • ImportError – возникает, когда оператор import не может найти определение модуля, или когда оператор не может найти имя файла, который должен быть импортирован;
  • IndexError – возникает, когда индекс последовательности находится вне допустимого диапазона;
  • KeyError – возникает, когда ключ сопоставления (dictionary key) не найден в наборе существующих ключей;
  • KeyboardInterrupt – возникает, когда пользователь нажимает клавишу прерывания(обычно Delete или Ctrl+C);
  • NameError – возникает, когда локальное или глобальное имя не найдено;
  • OSError – возникает, когда функция получает связанную с системой ошибку;
  • SyntaxError — возникает, когда синтаксическая ошибка встречается синтаксическим анализатором;
  • TypeError – возникает, когда операция или функция применяется к объекту несоответствующего типа. Связанное значение представляет собой строку, в которой приводятся подробные сведения о несоответствии типов;
  • ValueError – возникает, когда встроенная операция или функция получают аргумент, тип которого правильный, но неправильно значение, и ситуация не может описано более точно, как при возникновении IndexError;
  • ZeroDivisionError – возникает, когда второй аргумент операции division или modulo равен нулю;

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

Как обрабатывать исключения?

Обработка исключений в Пайтон – это очень просто. Потратим немного времени и напишем несколько примеров, которые их вызовут. Мы начнем с одной из самых элементарных проблем: деление на ноль.

1 / 0

Traceback (most recent call last):

    File «<string>», line 1, in <fragment>

ZeroDivisionError: integer division or modulo by zero

try:

    1 / 0

except ZeroDivisionError:

    print(«You cannot divide by zero!»)

Если мы обратимся к урокам элементарной математики, то вспомним, что на ноль делить нельзя. В Пайтоне данная операция вызовет ошибку, как мы можем видеть в примере выше. Чтобы поймать ошибку, мы завернем операцию в оператор try/except.

«Голое» исключение

Есть еще один способ поймать ошибку:

try:

    1 / 0

except:

    print(«You cannot divide by zero!»)

Но мы его не рекомендуем. На жаргоне Пайтона, это известно как голое исключение, что означает, что будут найдены вообще все исключения. Причина, по которой так делать не рекомендуется, заключается в том, что вы не узнаете, что именно за исключение вы выловите. Когда у вас возникло что-то в духе ZeroDivisionError, вы хотите выявить фрагмент, в котором происходит деление на ноль. В коде, написанном выше, вы не можете указать, что именно вам нужно выявить. Давайте взглянем еще на несколько примеров:

my_dict = {«a»:1, «b»:2, «c»:3}

try:

    value = my_dict[«d»]

except KeyError:

    print(«That key does not exist!»)

my_list = [1, 2, 3, 4, 5]

try:

    my_list[6]

except IndexError:

    print(«That index is not in the list!»)

В первом примере, мы создали словарь из трех элементов. После этого, мы попытались открыть доступ ключу, которого в словаре нет. Так как ключ не в словаре, возникает KeyError, которую мы выявили. Второй пример показывает список, длина которого состоит из пяти объектов. Мы попытались взять седьмой объект из индекса.

Есть вопросы по Python?

На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!

Telegram Чат & Канал

Вступите в наш дружный чат по Python и начните общение с единомышленниками! Станьте частью большого сообщества!

Паблик VK

Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!

Помните, что списки в Пайтоне начинаются с нуля, так что когда вы говорите 6, вы запрашиваете 7. В любом случае, в нашем списке только пять объектов, по этой причине возникает IndexError, которую мы выявили. Вы также можете выявить несколько ошибок за раз при помощи одного оператора. Для этого существует несколько различных способов. Давайте посмотрим:

my_dict = {«a»:1, «b»:2, «c»:3}

try:

    value = my_dict[«d»]

except IndexError:

    print(«This index does not exist!»)

except KeyError:

    print(«This key is not in the dictionary!»)

except:

    print(«Some other error occurred!»)

Это самый стандартный способ выявить несколько исключений. Сначала мы попробовали открыть доступ к несуществующему ключу, которого нет в нашем словаре. При помощи try/except мы проверили код на наличие ошибки KeyError, которая находится во втором операторе except. Обратите внимание на то, что в конце кода у нас появилась «голое» исключение. Обычно, это не рекомендуется, но вы, возможно, будете сталкиваться с этим время от времени, так что лучше быть проинформированным об этом. Кстати, также обратите внимание на то, что вам не нужно использовать целый блок кода для обработки нескольких исключений. Обычно, целый блок используется для выявления одного единственного исключения. Изучим второй способ выявления нескольких исключений:

try:

    value = my_dict[«d»]

except (IndexError, KeyError):

    print(«An IndexError or KeyError occurred!»)

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

В зависимости от сложности данной ошибки, вам может понадобиться выйти из программы. Иногда вам может понадобиться выполнить очистку, перед выходом из программы. Например, если вы открыли соединение с базой данных, вам нужно будет закрыть его, перед выходом из программы, или вы можете закончить с открытым соединением. Другой пример – закрытие дескриптора файла, к которому вы обращаетесь. Теперь нам нужно научиться убирать за собой. Это очень просто, если использовать оператор finally.

Оператор finally

Оператор finally очень прост в использовании. Давайте взглянем на нижеизложенный пример:

my_dict = {«a»:1, «b»:2, «c»:3}

try:

    value = my_dict[«d»]

except KeyError:

    print(«A KeyError occurred!»)

finally:

    print(«The finally statement has executed!»)

Если вы запустите это код, оно отобразиться и в операторе except и в finally. Весьма просто, не так ли? Теперь вы можете использовать оператор finally, чтобы убрать за собой. Вы можете также вписать код exit в конце оператора finally.

Попробуйте except или else

Оператор try/except также имеет пункт else. Он работает только в том случае, если в вашем коде нет ни единой ошибки. Давайте потратим немного времени и взглянем на парочку примеров:

my_dict = {«a»:1, «b»:2, «c»:3}

try:

    value = my_dict[«a»]

except KeyError:

    print(«A KeyError occurred!»)

else:

    print(«No error occurred!»)

Мы видим словарь, состоящий из трех элементов, и в операторе try/except мы открываем доступ к существующему ключу. Это работает, так что ошибка KeyError не возникает. Так как ошибки нет, else работает, и надпись“No error occurred!” появляется на экране. Теперь добавим оператор finally:

my_dict = {«a»:1, «b»:2, «c»:3}

try:

    value = my_dict[«a»]

except KeyError:

    print(«A KeyError occurred!»)

else:

    print(«No error occurred!»)

finally:

    print(«The finally statement ran!»)

В данном коде работают и оператор else и finally. Большую часть времени вы не будете сталкиваться с оператором else, используемый в том или ином коде, который следует за оператором try/except, если ни одна ошибка не была найдена. Единственное полезное применение оператора else, которое я видел, это когда вы хотите запустить вторую часть кода, в которой может быть ошибка. Конечно, если ошибка возникает в else, то она не будет поймана.

Подведем итоги

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

Являюсь администратором нескольких порталов по обучению языков программирования Python, Golang и Kotlin. В составе небольшой команды единомышленников, мы занимаемся популяризацией языков программирования на русскоязычную аудиторию. Большая часть статей была адаптирована нами на русский язык и распространяется бесплатно.

E-mail: vasile.buldumac@ati.utm.md

Образование
Universitatea Tehnică a Moldovei (utm.md)

  • 2014 — 2018 Технический Университет Молдовы, ИТ-Инженер. Тема дипломной работы «Автоматизация покупки и продажи криптовалюты используя технический анализ»
  • 2018 — 2020 Технический Университет Молдовы, Магистр, Магистерская диссертация «Идентификация человека в киберпространстве по фотографии лица»

Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Введение

В этом уроке вы узнаете о важном средстве языка, без которого крупная программа не может обойтись. Речь пойдет об исключениях. Что это такое, как ими пользоваться и как создавать собственные?

Исключительные ситуации или исключения (exceptions) – это ошибки, обнаруженные при исполнении. Например, к чему приведет попытка чтения несуществующего файла? Или если файл был случайно удален пока программа работала? Такие ситуации обрабатываются при помощи исключений.

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

Простейший пример исключения — деление на ноль:

>>> 100 / 0
Traceback (most recent call last):
  File "", line 1, in
    100 / 0
ZeroDivisionError: division by zero

В данном случае интерпретатор сообщил нам об исключении ZeroDivisionError – делении на ноль.

Traceback

В большой программе исключения часто возникают внутри. Чтобы упростить программисту понимание ошибки и причины такого поведения Python предлагает Traceback или в сленге – трэйс. Каждое исключение содержит краткую информацию, но при этом полную, информацию о месте появления ошибки. По трэйсу найти и исправить ошибку становится проще.

Рассмотрим такой пример:

Traceback (most recent call last):
  File "/home/username/Develop/test/app.py", line 862, in _handle
    return route.call(**args)
  File "/home/username/Develop/test/app.py", line 1729, in wrapper
    rv = callback(*a, **ka)
  File "/home/username/Develop/test/__init__.py", line 76, in wrapper
    body = callback(*args, **kwargs)
  File "/home/username/Develop/test/my_app.py", line 16, in index
    raise Exception('test exception')

В данном примере чётко видно, какой путь исполнения у программы. Смотрим снизу вверх и по шагам понимаем, как же мы докатились до такого исключения.

Рассмотрим какие ещё встречаются комментарии к исключениям:

>>> 2 + '1'

Traceback (most recent call last):
  File "", line 1, in
    2 + '1'
TypeError: unsupported operand type(s) for +: 'int' and 'str'

В данном примере при попытке сложить целое число и строку мы получаем исключение TypeError. В описании сразу же становится ясно, что же мы не так написали.

>>> int('qwerty')

Traceback (most recent call last):
  File "", line 1, in
    int('qwerty')
ValueError: invalid literal for int() with base 10: 'qwerty'

Приведение строчки к целому числу приводит к исключению ValueError.

В трэйсе этих двух примеров можно прочесть, что в таком-то файле на такой-то строчке есть ошибки.

На этом список встроенных исключений не заканчивается, в следующем разделе рассмотрены основные исключения и причины их возникновения.

Иерархия исключений

Исключение, которое вы не увидите при выполнении кода – это BaseException – базовое исключение, от которого берут начало остальные.

В иерархии исключений две основные группы:

  • Системные исключения и ошибки
  • Обыкновенные исключения

Если обработку первых лучше не делать (если и делать, то надо четко понимать для чего), то обработку вторых целиком и полностью Python возлагает на плечи программиста.

К системным можно смело отнести:

  • SystemExit – исключение, порождаемое функцией sys.exit при выходе из программы.
  • KeyboardInterrupt – возникает при прерывании программы пользователем (обычно сочетанием клавиш Ctrl+C).
  • GeneratorExit — возникает при вызове метода close объекта generator.

Остальные исключения – это «обыкновенные». Спектр уже готовых исключений велик.

Для Python2 иерархию исключений можно представить так:

Список исключений покрывает большой объем ситуаций и ошибок программиста. Если предупреждения (warning) только просят обратить внимание, то ошибки уже могут остановить исполнение программы.

В Python3 появились новые исключения и иерархия стала такова:

В целом заметно, что при создании Python3 добавлен блок новых исключений. Но даже этих почти 70 исключений не хватает при написании программ на языке Python.

Использование исключений

Мы рассмотрели что такое исключения, какие они бывают и как их анализировать. Но до сих пор явно не рассмотрели такую важную вещь, как их использование.

Начнем с обработки.

Обработка исключений

Давайте рассмотрим случай с делением на 0.

>>> a = 100
>>> b = 0
>>> c = a / b

Данный код приведет к исключению ZeroDivisionError. Чтобы этого не случилось, воспользуемся конструкцией try..except, например, так:

>>> try:
...     a = 100
...     b = 0
...     c = a / b
... except ZeroDivisionError as e:
...     print(e)
...
division by zero

Если исполнить этот код, то на консоль будет выведена строка «integer division or modulo by zero«. Казалось бы, что толком ничего это нам не дало, ошибка все также есть. Однако в блок except можно поместить обработку.

Например, мы условились, что значение переменной c в случае ошибки деления равно -1. Тогда модифицируем код:

>>> try:
...     a = 100
...     b = 0
...     c = a / b
... except ZeroDivisionError as e:
...     c = -1
>>> c
-1

Перед тем как идти дальше, рассмотрим ещё одну возможность.

Пускай у нас файл с данными в файловой системе, и необходимо его прочитать. В этом случае сразу же всплывают несколько исключительных ситуаций, такие как: нет файла, файл битый, файл пустой (по заданию мы знаем, что в нём данные) и другие.

Используя исключения, можно вот так решить эту задачу:

try:
    filepath = 'test_file.txt'
    with open(filepath, 'r') as fio:
        result = fio.readlines()
    if not result:
        raise Exception("File is empty")

except IOError as e:
    result = []
except Exception as e:
    result = []
    print(e)

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

Если обработка для разных типов исключений одинакова, то уменьшить количество кода становится не проблемой:

try:
    your_code
except (IOError, Exception) as e:
    print(e)

Вызов исключений

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

На сленге программистов «бросить исключение» означает написать код, который при исполнении будет инициировать исключительную ситуацию.

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

Чтобы бросить исключение необходимо воспользоваться raise

Пример:

raise IOError("текст исключения")

где IOError это класс исключения.

Если при обработке исключения вы желаете пробросить его ещё выше, то следует написать такой код:

try:
    your_code
except Exception as e:
    raise

Собственные исключения

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

В минимальном исполнении необходимо наследоваться от какого-нибудь класса в иерархии исключений. Например так:

class MyException(Exception):
    pass

Тогда можно бросить своё исключение:

raise MyException(Exception)

Легко заметить, мы создаем класс, а значит всё, что мы знаем о классах, справедливо и для исключений. Можно завести переменные и делать их обработку.

Как правило, исключения это очень маленькие классы. Они должны выполняться максимально быстро.

Дополнение: Полная форма try..except

Форма try...except не полная, полной же является try..except..else..finally.

Применение полной конструкции может заметно упростить код, а также сделать его более безопасным.

Представим, что в программе происходит чтение файла и необходимо убедиться, что объект файла был корректно закрыт и что не возникло никакого исключения. Этого можно достичь с применением блока finally.

Иными словами, finally выполняет блок инструкций в любом случае, было ли исключение, или нет. А инструкция else выполняется в том случае, если исключения не было.

В целом, использование полной формы таково:

try:
    исполяем какой-то код
except Exception as e:
    обработка исключения
else:
    код, который будет исполнен в случае, когда не возникает исключения
finally:
    код, который гарантированно будет исполнен последним (всегда исполняется)

Выводы

В уроке рассмотрены вопросы связанные с исключениями:

  • Что такое исключение
  • Какие типы исключений присутствуют в языке
  • Как обрабатывать исключения
  • Как вызвать исключения
  • Как создавать собственные исключения

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

Video: errors and exceptions.

Imperial students can also watch this video on Panopto.

It is a sight familiar to every programmer: instead of producing the
desired result, the screen is filled with seemingly unintelligible
garbage because an error has occurred. Producing errors is an
unavoidable part of programming, so learning to understand and correct
them is an essential part of learning to program.

6.1. What is an error?¶

In mathematics, we are used to the idea that an expression might not
be defined. For example, in the absence of further information,
(0/0) does not have a well-defined value. Similarly, the string
of symbols (3 times %) does not have a mathematical
meaning. It is likewise very easy to create statements or expressions
in a programming language which either don’t have a well-defined
meaning, or which just don’t amount to a meaningful statement within
the rules of the language. A mathematician confronting an undefined
mathematical expression can do little else than throw up their hands
and ask the author what they meant. The Python interpreter, upon
encountering code which has no defined meaning, responds similarly;
though rather than raising its non-existent hands, it raises an
exception. It is then up to the programmer to divine what to do next.

Let’s take a look at what Python does in response to a simple
error:

In [3]: 0./0.
--------------------------------------------------------------------------
ZeroDivisionError                        Traceback (most recent call last)
Cell In [3], line 1
----> 1 0./0.

ZeroDivisionError: float division by zero

An important rule in interpreting Python errors, the reasons for which we will
return to, is to always read the error message from the bottom up. In
this case, the last line contains the name of the exception which has
been raised, ZeroDivisionError, followed by a colon, followed by
a descriptive string providing more information about what has gone
wrong. In this case, that more or less says the same as the exception
name, but that won’t be the case for all exceptions. The four lines
above the exception are called a traceback. We’ll return to
interpreting tracebacks presently. In this case the error is easy to interpret
and understand: the code divided the float value 0. by another zero,
and this does not have a well-defined result in Python’s arithmetic system.

6.1.1. Syntax errors¶

Now consider the case of an expression that doesn’t make mathematical sense:

In [5]: 3 * %
Cell In [5], line 1
    3 * %
        ^
SyntaxError: invalid syntax

This creates a syntax error, signified by a SyntaxError exception. In
programming languages, as with human languages, the syntax is the set of rules
which defines which expressions are well-formed. Notice that the earlier lines
of a syntax error appear somewhat different to those of the previous exception.
Almost all exceptions occur because the Python interpreter attempts to
evaluate a statement or expression and encounters a problem. Syntax errors are
a special case: when a syntax error occurs, the interpreter can’t even get as
far as attempting to evaluate because the sequence of characters it has been
asked to execute do not make sense in Python. This time, the error message
shows the precise point in the line at which the Python interpreter found a
problem. This is indicated by the caret symbol (^). In this case, the reason
that the expression doesn’t make any sense is that the modulo operator (%) is
not a permissible second operand to multiplication (*), so the Python
interpreter places the caret under the modulo operator.

Even though the Python interpreter will highlight the point at which
the syntax doesn’t make sense, this might not quite actually be the
point at which you made the mistake. In particular, failing to finish
a line of code will often result in the interpreter assuming that the
expression continues on the next line of program text, resulting in
the syntax error appearing to be one line later than it really
occurs. Consider the following code:

The error here is a missing closing bracket on the first line, however
the error message which the Python interpreter prints when this code is run is:

  File "syntax_error.py", line 2
    print(a)
        ^
SyntaxError: invalid syntax

To understand why Python reports the error on the line following the
actual problem, we need to understand that the missing closing bracket
was not by itself an error. The user could, after all, validly
continue the tuple constructor on the next line. For example,
the following code would be completely valid:

This means that the Python interpreter can only know that something is
wrong when it sees print, because print cannot follow 2 in a
tuple constructor. The interpreter, therefore, reports that the print
is a syntax error.

Hint

If the Python interpreter reports a syntax error at the start of a
line, always check to see if the actual error is on the previous
line.

6.2. Exceptions¶

Aside from syntax errors, which are handled directly by the
interpreter, errors occur when Python code is executed and something
goes wrong. In these cases the Python code in which the problem is
encountered must signal this to the interpreter. It does this using a
special kind of object called an exception. When an exception
occurs, the interpreter stops executing the usual sequence of Python
commands. Unless the programmer has taken special measures, to which
we will return in Section 6.5, the execution will
cease and an error message will result.

Because there are many things that can go wrong, Python has many types
of exception built in. For example, if we attempt to access the number
2 position in a tuple with only two entries, then an
IndexError exception occurs:

In [1]: (0, 1)[2]
--------------------------------------------------------------------------
IndexError                               Traceback (most recent call last)
Cell In [1], line 1
----> 1 (0, 1)[2]

IndexError: tuple index out of range

The exception type provides some indication as
to what has gone wrong, and there is usually also an error message and
sometimes more data to help diagnose the problem. The full list
of built-in exceptions
is available in the
Python documentation. Python developers can define their own
exceptions so there are many more defined in third-party packages. We will
turn to the subject of defining new exception classes in
Section 7.4.

6.3. Tracebacks: finding errors¶

Video: tracebacks.

Imperial students can also watch this video on Panopto.

The errors we have looked at so far have all been located in the top
level of code either typed directly into iPython or executed in a
script. However, what happens if an error occurs in a function call or
even several functions down? Consider the following code, which uses
the Polynomial class from
Chapter 3:

In [1]: from example_code.polynomial import Polynomial

In [2]: p = Polynomial(("a", "b"))

In [3]: print(p)
bx + a

Perhaps surprisingly, it turns out that we are able to define a polynomial
whose coefficients are letters, and we can even print the resulting object.
However, if we attempt to add this polynomial to the number 1, we are in
trouble:

In [4]: print(1 + p)
--------------------------------------------------------------------------
TypeError                                Traceback (most recent call last)
Cell In [4], line 1
----> 1 print(1 + p)

File ~/docs/principles_of_programming/object-oriented-programming/example_code/polynomial.py:59, in Polynomial.__radd__(self, other)
    58 def __radd__(self, other):
---> 59     return self + other

File ~/docs/principles_of_programming/object-oriented-programming/example_code/polynomial.py:38, in Polynomial.__add__(self, other)
    36 def __add__(self, other):
    37     if isinstance(other, Number):
---> 38         return Polynomial((self.coefficients[0] + other,)
    39                           + self.coefficients[1:])
    41     elif isinstance(other, Polynomial):
    42         # Work out how many coefficient places the two polynomials have in
    43         # common.
    44         common = min(self.degree(), other.degree()) + 1

TypeError: can only concatenate str (not "int") to str

This is a much larger error message than those we have previously
encountered, however, the same principles apply. We start by reading
the last line. This tells us that the error was a TypeError
caused by attempting to concatenate (add) an integer to a
string. Where did this error occur? This is a more involved question
than it may first appear, and the rest of the error message above is
designed to help us answer this question. This type of error message
is called a traceback, as the second line of the error message
suggests. In order to understand this message, we need to understand a
little about how a Python program is executed, and in particular about
the call stack.

6.3.1. The call stack¶

Video: the call stack.

Imperial students can also watch this video on Panopto.

A Python program is a sequence of Python statements, which are
executed in a sequence determined by the flow control logic of the
program itself. Each statement contains zero or more function calls 1,
which are executed in the course of evaluating that statement.

One of the most basic features of a function call is that the contents
of the function execute, and then the code which called the function
continues on from the point of the function call, using the return
value of the function in place of the call. Let’s think about what
happens when this occurs. Before calling the function, there is a
large amount of information which describes the context of the current
program execution. For example, there are all of the module, function,
and variable names which are in scope, and there is the record of
which instruction is next to be executed. This collection of
information about the current execution context is called a
stack frame. We learned about stacks in
Section 5.1, and the term “stack frame” is not a coincidence. The
Python interpreter maintains a stack of stack frames called
the call stack. It is also sometimes called the
execution stack or interpreter stack.

The first frame on the stack contains the execution context for the
Python script that the user ran or, in the case where the user worked
interactively, for the iPython shell or Jupyter notebook into which
the user was typing. When a function is called, the Python interpreter
creates a new stack frame containing the local execution context of
that function and pushes it onto the call stack. When that function
returns, its stack frame is popped from the call stack, leaving the
interpreter to continue at the next instruction in the stack frame
from which the function was called. Because functions can call
functions which call functions and so on in a nearly limitless
sequence, there can be a number of stack frames in existence at any
time.

6.3.2. Interpreting tracebacks¶

Let’s return to the traceback for our erroneous polynomial addition:

In [4]: print(1 + p)
--------------------------------------------------------------------------
TypeError                                Traceback (most recent call last)
Cell In [4], line 1
----> 1 print(1 + p)

File ~/docs/principles_of_programming/object-oriented-programming/example_code/polynomial.py:59, in Polynomial.__radd__(self, other)
    58 def __radd__(self, other):
---> 59     return self + other

File ~/docs/principles_of_programming/object-oriented-programming/example_code/polynomial.py:38, in Polynomial.__add__(self, other)
    36 def __add__(self, other):
    37     if isinstance(other, Number):
---> 38         return Polynomial((self.coefficients[0] + other,)
    39                           + self.coefficients[1:])
    41     elif isinstance(other, Polynomial):
    42         # Work out how many coefficient places the two polynomials have in
    43         # common.
    44         common = min(self.degree(), other.degree()) + 1

TypeError: can only concatenate str (not "int") to str

This shows information about a call stack comprising three
stack frames. Look first at the bottom-most
frame, which corresponds to the function in which the exception
occurred. The traceback for this frame starts:

File ~/docs/principles_of_programming/object-oriented-programming/example_code/polynomial.py:38, in Polynomial.__add__(self, other)

This indicates that the frame describes code in the file polynomial.py
(which, on the author’s computer, is located in the folder
~/principles_of_programming/object-oriented-programming/example_code/).
Specifically, the stack frame describes the execution of the __add__()
method, which is the special method responsible for polynomial
addition. The lines below this show the line on which execution stopped (line
38, in this case) and a couple of lines on either side, for context.

The stack frame above this shows the function from which the __add__()
method was called. In this case, this is the reverse addition special
method
, __radd__(). On line 59 __radd__() calls __add__()
through the addition of self and other.

Finally, the top stack frame corresponds to the command that the user typed in
iPython. This stack frame looks a little different from the others. Instead of
a file name there and a function name there is Cell In [4], line 1. This
indicates that the exception was raised on line 1 of the IPython cell In [4].

Hint

Older versions of Python display less helpful location information for the
top stack frame, so in that case you might see something like
<ipython-input-2-c3aeb16193d4> in rather than
Cell In [4], line 1.

Hint

The proximate cause of the error will be in the last stack
frame
printed, so always read the traceback from the
bottom up. However, the ultimate cause of the problem may
be further up the call stack, so don’t stop reading at the
bottom frame!

6.4. Raising exceptions¶

Video: raising an exception.

Imperial students can also watch this video on Panopto.

Thus far we’ve noticed that an exception occurs when something goes
wrong in a program, and that the Python interpreter will stop
at that point and print out a traceback. We’ll now examine the
process by which an exception occurs.

An exception is triggered using the raise keyword. For
example, suppose we want to ensure that the input to our Fibonacci
function is an integer. All Python integers are instances of numbers.Integral, so we can check this. If we
find a non-integer type then the consequence should be a
TypeError. This is achieved by raising the appropriate
exception, using the raise statement. The keyword
raise is followed by the exception. Almost all exceptions
take a string argument, which is the error message to be printed. In
Listing 6.1, we inform the user that we were expecting an
integer rather than the type actually provided.

Listing 6.1 A version of the Fibonacci function which raises an
exception if a non-integer type is passed as the
argument.

 1from numbers import Integral
 2
 3
 4def typesafe_fib(n):
 5    """Return the n-th Fibonacci number, raising an exception if a
 6    non-integer is passed as n."""
 7    if not isinstance(n, Integral):
 8            raise TypeError(
 9                f"fib expects an integer, not a {type(n).__name__}"
10            )
11    if n == 0:
12        return 0
13    elif n == 1:
14        return 1
15    else:
16        return fib(n-2) + fib(n-1)

If we now pass a non-integer value to this function, we observe the following:

In [1]: from fibonacci.typesafe_fibonacci import typesafe_fib
In [2]: typesafe_fib(1.5)
--------------------------------------------------------------------------
TypeError                                Traceback (most recent call last)
Cell In [2], line 1
----> 1 typesafe_fib(1.5)

File ~/docs/principles_of_programming/object-oriented-programming/fibonacci/typesafe_fibonacci.py:8, in typesafe_fib(n)
    5 """Return the n-th Fibonacci number, raising an exception if a
    6 non-integer is passed as n."""
    7 if not isinstance(n, Integral):
----> 8     raise TypeError(
    9         f"fib expects an integer, not a {type(n).__name__}"
    10     )
    11 if n == 0:
    12     return 0

TypeError: fib expects an integer, not a float

This is exactly what we have come to expect: execution has stopped and
we see a traceback. Notice that the final line is the error
message that we passed to TypeError. The only difference
between this and the previous errors we have seen is that the bottom
stack frame explicitly shows the exception being raised, while
previously the stack showed a piece of code where an error had
occurred. This minor difference has to do with whether the particular
piece of code where the exception occurred is written in Python, or is
written in a language such as C and called from Python. This
distinction is of negligible importance for our current purposes.

Note

An exceptionally common mistake that programmers make when first
trying to work with exceptions is to write:

instead of:

This mistake is the result of a confusion about what
return and raise do. return means
“the function is finished, here is the result”. raise
means “something exceptional happened, execution is stopping
without a result”.

6.5. Handling exceptions¶

Video: handling exceptions.

Imperial students can also watch this video on Panopto.

So far we have seen several different sorts of exception, how to raise them,
and how to understand the resulting traceback. The traceback is
very helpful if the exception was caused by a bug in our code, as it is a rich
source of the information needed to understand and correct the error. However,
sometimes an exception is a valid result of a valid input, and we just need the
program to do something out of the ordinary to deal with the situation. For
example, Euclid’s algorithm for finding the greatest common divisor of
(a) and (b) can very nearly be written recursively as:

def gcd(a, b):
    return gcd(b, a % b)

This works right up to the point where b becomes zero, at which
point we should stop the recursion and return a. What actually
happens if we run this code? Let’s try:

In [2]: gcd(10, 12)
--------------------------------------------------------------------------
ZeroDivisionError                        Traceback (most recent call last)
Cell In[2], line 1
----> 1 gcd(10, 12)

Cell In[1], line 2, in gcd(a, b)
    1 def gcd(a, b):
----> 2     return gcd(b, a % b)

Cell In[1], line 2, in gcd(a, b)
    1 def gcd(a, b):
----> 2     return gcd(b, a % b)

    [... skipping similar frames: gcd at line 2 (1 times)]

Cell In[1], line 2, in gcd(a, b)
    1 def gcd(a, b):
----> 2     return gcd(b, a % b)

ZeroDivisionError: integer modulo by zero

Notice how the recursive call to gcd() causes several
stack frames that look the same. Indeed, the Python
interpreter even notices the similarity and skips over one. That makes
sense: gcd() calls itself until b is zero, and then we get a
ZeroDivisionError because modulo zero is undefined. To
complete this function, what we need to do is to tell Python to stop
at the ZeroDivisionError and return a
instead. Listing 6.2 illustrates how this can be achieved.

Listing 6.2 A recursive implementation of Euclid’s algorithm which
catches the ZeroDivisionError to implement the
base case.

1def gcd(a, b):
2    try:
3        return gcd(b, a % b)
4    except ZeroDivisionError:
5        return a

The new structure here is the tryexcept
block. The try keyword defines a block of code, in this
case just containing return gcd(b, a % b). The except is
optionally followed by an exception class, or a tuple of exception
classes. This case, the except is only followed by the
ZeroDivisionError class. What this means is that if a
ZeroDivisionError is raised by any of the code inside the
try block then, instead of execution halting and a
traceback being printed, the code inside the except
block is run.

In the example here, this means that once b is zero, instead of
gcd being called a further time, a is returned. If we run this
version of gcd() then we have, as we might expect:

In [2]: gcd(10, 12)
Out[2]: 2

6.5.1. Except clauses¶

Video: further exception handling.

Imperial students can also watch this video on Panopto.

Let’s look in a little more detail at how except works. The full
version of the except statement takes a tuple of exception classes. If an
exception is raised matching any of the exceptions in that tuple then the code
in the except block is executed.

It’s also possible to have more than one except block following a
single try statement. In this case, the first except block for which
the exception matches the list of exceptions is executed. For example:

In [1]: try:
    ...:     0./0
    ...: except TypeError, KeyError:
    ...:     print("Type or key error")
    ...: except ZeroDivisionError:
    ...:     print("Zero division error")
    ...:
Zero division error

Note

It is also possible to omit the list of exceptions after except.
In this case, the except block will match any exception which is raised in
the corresponding try block. Using unconstrained except blocks like this is
a somewhat dangerous strategy. Usually, the except block will be designed
to deal with a particular type of exceptional circumstance. However, an
except block that catches any exception may well be triggered by a completely
different exception, in which case it will just make the error more
confusing by obscuring where the issue actually occurred.

6.5.2. Else and finally¶

It can also be useful to execute some code only if an exception is not raised.
This can be achieved using an else clause. An else clause after a try block is caused only if no exception was
raised.

It is also sometimes useful to be able to execute some code no matter what
happened in the try block. If there is a finally clause
then the code it contains will be executed if either an exception is raised and
handled by an except block, or no exception occurred. This
plethora of variants on the try block can get a little confusing, so
a practical example may help. Listing 6.3 prints out a different
message for each type of clause.

Listing 6.3 A demonstration of all the clauses of the try block.

 1def except_demo(n):
 2    """Demonstrate all the clauses of a `try` block."""
 3
 4    print(f"Attempting division by {n}")
 5    try:
 6        print(0./n)
 7    except ZeroDivisionError:
 8        print("Zero division")
 9    except TypeError:
10        print(f"Can't divide by a {type(n).__name__}.")
11    else:
12        print("Division successful.")
13    finally:
14        print("Finishing up.")

If we execute except_demo() for a variety of
arguments, we can observe this complete try block in action. First,
we provide an input which is a valid divisor:

In [1]: from example_code.try_except import except_demo
In [2]: except_demo(1)
Attempting division by 1
0.0
Division successful.
Finishing up.

Here we can see the output of the division, the else block, and
the finally block. Next we divide by zero:

In [3]: except_demo(0)
Attempting division by 0
Zero division
Finishing up.

This caused a ZeroDivisionError, which was caught by the first
except clause. Since an exception was raised, the the else block is not executed, but the finally block still executes.
Similarly, if we attempt to divide by a string, we are caught by the second
except clause:

In [4]: except_demo("frog")
Attempting division by frog
Can't divide by a str.
Finishing up.

6.5.3. Exception handling and the call stack¶

An except block will handle any matching exception raised in the
preceding try block. The try block can, of
course, contain any code at all. In particular it might contain
function calls which themselves may well call further functions. This
means that an exception might occur several stack frames down the call stack from the try
clause. Indeed, some of the functions called might themselves contain
try blocks with the result that an exception is raised at a
point which is ultimately inside several try blocks.

The Python interpreter deals with this situation by starting from the
current stack frame and working upwards, a process known as unwinding
the stack
. Listing 6.4 shows pseudocode for this process.

Listing 6.4 Pseudocode for the process of unwinding the stack, in which the
interpreter successively looks through higher stack frames to search
for an except clause matching the exception that has just
been raised.

while call stack not empty:
    if current execution point is in a try block 
            with an except matching the current exception:
        execution continues in the except block
    else:
        pop the current stack frame off the call stack

# Call stack is now empty
print traceback and exit

6.6. Exceptions are not always errors¶

This chapter is called “Errors and exceptions”, so it is appropriate
to finish by drawing attention to the distinction between these two
concepts. While user errors and bugs in programs typically result in
an exception being raised, it is not the case that all exceptions
result from errors. The name “exception” means what it says, it is an
event whose occurrence requires an exception to the normal sequence of
execution.

The StopIteration exception which we encountered in
Section 5.6 is a good example of an exception
which does not indicate an error. The end of the set of things to be
iterated over does not indicate that something has gone wrong, but it
is an exception to the usual behaviour of __next__(),
which Python needs to handle in a different way from simply returning
the next item.

6.7. Glossary¶

call stack¶
execution stack¶
interpreter stack¶

The stack of stack frames in existence. The
current item on the stack is the currently executing function,
while the deepest item is the stack frame corresponding to the
user script or interpreter.

exception¶

An object representing an out of the ordinary event which has
occurred during the execution of some Python code. When an
exception is raised the
Python interpreter doesn’t continue to execute the
following line of code. Instead, the exception is either
handled or execution stops and a
traceback is printed.

stack frame¶

An object encapsulating the set of variables which define the
execution of a Python script or function. This information
includes the code being executed, all the local and global
names which are visible, the last instruction that was
executed, and a reference to the stack frame which called this
function.

syntax¶

The set of rules which define what is a well-formed Python
statement. For example the rule that statements which start
blocks must end with a colon (:) is a syntax rule.

syntax error¶

The exception which occurs when a statement violates
the syntax rules of Python. Mismatched brackets,
missing commas, and incorrect indentation are all examples of
syntax errors.

traceback¶
stack trace¶
back trace¶

A text representation of the call stack. A traceback
shows a few lines of code around the current execution point
in each stack frame, with the current frame at the
bottom and the outermost frame at the top.

6.8. Exercises¶

Using the information on the book website
obtain the skeleton code for these exercises.

Exercise 6.1

The Newton-Raphson method is an iterative method for approximately solving
equations of the form (f(x)=0). Starting from an initial guess, a
series of (hopefully convergent) approximations to the solution is computed:

[x_{n+1} = x_n — frac{f(x_n)}{f'(x_n)}]

The iteration concludes successfully if (|f(x_{n+1})| < epsilon) for some
user-specified tolerance (epsilon>0). The sequence is not guaranteed
to converge for all combinations of function and starting point, so the
iteration should fail if (n) exceeds a user-specified number of
iterations.

The skeleton code for this chapter contains a function
nonlinear_solvers.solvers.newton_raphson() which takes as arguments a
function, its derivative and a starting point for the iteration. It can also
optionally be passed a value for (epsilon) and a maximum number of
iterations to execute. Implement this function. If the iteration succeeds
then the last iterate, (x_{n+1}), should be returned.

nonlinear_solvers.solvers also defines an exception,
ConvergenceError. If the Newton-Raphson iteration exceeds the
number of iterations allowed then this exception should be raised, with an
appropriate error message.

Exercise 6.2

The bisection method is a slower but more robust iterative solver. It requires a
function (f) and two starting points (x_0) and (x_1) such
that (f(x_0)) and (f(x_1)) differ in sign. At each stage of the
iteration, the function is evaluated at the midpoint of the current points
(x^* = (x_0 + x_1)/2). If (|,f(x^*)|<epsilon) then the iteration
terminates successfully. Otherwise, (x^*) replaces (x_0) if
(f(x_0)) and (f(x^*)) have the same sign, and replaces
(x_1) otherwise.

Implement nonlinear_solvers.solvers.bisection(). As before, if the
iteration succeeds then return the last value of (x). If the maximum
number of iterations is exceeded, raise ConvergenceError with a
suitable error message. The bisection method has a further failure mode. If
(f(x_0)) and (f(x_1)) do not differ in sign then your code
should raise ValueError with a suitable message.

Exercise 6.3

Implement the function nonlinear_solvers.solvers.solve(). This code
should first attempt to solve (f(x)=0) using your Newton-Raphson
function. If that fails it should catch the exception and instead try using
your bisection function.

Footnotes

1

“Function call” here includes method calls and
operations implemented using a special method.

2

https://object-oriented-python.github.io/edition2/exercises.html

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии

А вот еще интересные материалы:

  • Яшка сломя голову остановился исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного где ошибка
  • Intcoed sys ошибка windows 11
  • Intarder power limited ошибка рено премиум 420 dci