Исключения

Всякие недопустимые операции типа деления на 0 или открытия несуществующего файла приводят к возбуждению исключений. Интерпретатор питон печатает подробную и понятную информацию об исключении. Если это интерактивный интерпретатор, то сессия продолжается; исли это программа, то её выполнение прекращается. В питоне отладчик приходится использовать гораздо реже, чем в более низкоуровневых языках, потому что эти сообщения интерпретатора позволяют сразу понять, где и что неверно. Впрочем, иногда приходится использовать и отладчик. Допустим, из сообщения об ошибке Вы поняли, что некоторая функция вызвана со строковым аргументом, а Вы про него думали, что он число. Тогда приходится искать - какая сволочь испортила мою переменную?

In [1]:
1/0
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-1-05c9758a9c21> in <module>()
----> 1 1/0

ZeroDivisionError: division by zero

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

In [2]:
try:
    x=0
    x=1/x
except ZeroDivisionError:
    x=5
In [3]:
x
Out[3]:
5
In [4]:
try:
    s='xyzzy'
    f=open(s)
except IOError:
    print('cannot open '+s)
cannot open xyzzy

Исключения - это объекты. Класс Exception являестя корнем дерева классов исключений. Этот объект можно поймать и исследовать.

In [5]:
try:
    x=1/0
except Exception as err:
    print(type(err))
    print(err)
    print(repr(err))
    print(err.args)
<class 'ZeroDivisionError'>
division by zero
ZeroDivisionError('division by zero',)
('division by zero',)

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

In [6]:
raise NameError('Hi there')
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-6-d36a3cf2a944> in <module>()
----> 1 raise NameError('Hi there')

NameError: Hi there

Вот более полезный пример.

In [7]:
def f(x):
    if x==0:
        raise ValueError('x should not be 0')
    return x
In [8]:
try:
    x=f(1)
    x=f(0)
except ValueError as err:
    print(repr(err))
ValueError('x should not be 0',)
In [9]:
x
Out[9]:
1

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

In [10]:
class MyError(Exception):
    
    def __init__(self,value):
        self.value=value
        
    def __str__(self):
        return str(self.value)
In [11]:
def f(x):
    if x<0:
        raise MyError(x)
    else:
        return x
In [12]:
try:
    x=f(2)
    x=f(-2)
except MyError as err:
    print(err)
-2
In [13]:
x
Out[13]:
2