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
Зарегистрируйтесь для доступа к 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:
код, который гарантированно будет исполнен последним (всегда исполняется)
Выводы
В уроке рассмотрены вопросы связанные с исключениями:
- Что такое исключение
- Какие типы исключений присутствуют в языке
- Как обрабатывать исключения
- Как вызвать исключения
- Как создавать собственные исключения
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты.
Урок 18. Exceptions.
Что вы предпринимаете, когда с работой вашей программы что-то идет не так? Допустим, вы пытаетесь открыть файл, но вы ввели неверный путь, или вы хотите узнать информацию у пользователей и они пишут какую-то бессмыслицу. Вы не хотите, чтобы ваша программа крэшилась, по-этому вы выполняете обработку исключений. В Пайтоне, конструкция всегда обернута в то, что называется 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 равен нулю;
Существует много других исключений, но вы вряд ли будете сталкиваться с ними так же часто.
Как обрабатывать исключения?
Обработка исключений в Пайтон – это очень просто. Потратим немного времени и напишем несколько примеров, которые их вызовут. Мы начнем с одной из самых элементарных проблем: деление на ноль.
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!")
>>> 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, которую мы выявили. Второй пример показывает список, длина которого состоит из пяти объектов. Мы попытались взять седьмой объект из индекса.
Помните, что списки в Пайтоне начинаются с нуля, так что когда вы говорите 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, то она не будет поймана.
Оператор raise
Если в вашем коде какие-либо данные не соответсвуют вашим ожиданиям, вы всегда можете вызвать исключение если вам это необходимо, для этого используется ключевое слово raise
.
def even_the_odds(odds): if odds % 2 != 1: raise ValueError("Did not get an odd number") return odds + 1
Любое исключение завершает наш код, а значит, что до возврата в случае исключения функция не дойдет.
Мы можем использовать raise
внутри любой конструкции, допустим нам нужно отправлять ошибку на сторонний сервис, но не обрабатывать её
try: do_stuff(resource) except SomeException as e: log_error(e) raise # re-raise the error finally: free_expensive_resource(resource)
raise
в этом случае просто повторится
еще один такой пример
try: 5 / 0 except ZeroDivisionError: print("Got an error") raise
Имейте в виду, однако, что кто-то еще выше в стеке вызовов может все же перехватить исключение и как-то обработать его. Готовый вывод может быть неприятным в этом случае, потому что это произойдет в любом случае (пойман или не пойман). Поэтому может быть лучше создать другое исключение, содержащее ваш комментарий о ситуации, а также исходное исключение:
try: 5 / 0 except ZeroDivisionError as e: raise ZeroDivisionError("Got an error", e)
в переменной e
будет хранится вся информация о исключении, и таким рейзом мы вызовем нужный нам тип исключения, с нашим коментарием, и всей системной информацией.
Исключения тоже объекты
Исключением являются только обычные объекты Python , которые наследуют от встроенного BaseException . Сценарий Python может использовать raise заявление , чтобы прервать выполнение, в результате чего Python для печати трассировки стеки из стека вызовов в этой точке и представление экземпляра исключения.
Например:
>>> def failing_function(): ... raise ValueError('Example error!') >>> failing_function() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in failing_function ValueError: Example error!
который говорит , что ValueError
с сообщением ‘Example error!’ был поднят нашей failing_function()
, который был выполнен в интерпретаторе.
Код вызова может выбрать обработку любых исключений, которые может вызвать вызов:
>>> try: ... failing_function() ... except ValueError: ... print('Handled the error') Handled the error
Или вывесли оригинальный текст:
>>> try: ... failing_function() ... except ValueError as e: ... print('Caught exception', repr(e)) Caught exception ValueError('Example error!',)
Создание пользовательских типов исключений
Создайте класс , унаследованный от Exception :
class FooException(Exception): pass try: raise FooException("insert description here") except FooException: print("A FooException was raised.")
или другой тип исключения:
class NegativeError(ValueError): pass def foo(x): # function that only accepts positive values of x if x < 0: raise NegativeError("Cannot process negative numbers") ... # rest of function body try: result = foo(int(input("Enter a positive integer: "))) # raw_input in Python 2.x except NegativeError: print("You entered a negative number!") else: print("The result was " + str(result))