Исключения. Исключения. bash exeption

Исключения.

Open in new window

# Ошибки

Ошибки в программе Python возникают при исполнении кода, т. к. процесс компиляции отсутствует.

Ошибки в коде вызывают исключения, и если они не отработаны, то работа программы приостанавливается.

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

Синтаксические ошибки.

Так же известные как ошибки парсинга.

Например такой код вызовет.

while True print 'Hello world'

>>> while True print 'Hello world'
  File "<stdin>", line 1, in ?
    while True print 'Hello world'
                   ^
SyntaxError: invalid syntax

В этом примере мы пропустили знак : Маркер >>> указывает на строку с ошибкой, за которой следует ее номер.

Исключения и их обработка.

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

Например попытаемся поделить два числа, вводимых пользователем с клавиатуры.

x = input('first number: ')
y = input('second number: ')
print('is: %s' % x/y)

>>> TypeError: unsupported operand type(s) for /: 'str' and 'int'

Мы получим исключение несоответствия типов при форматировании строки.

Добавим обработчик исключения.

x = input('first number: ')
y = input('second number: ')
try:
    print('is: %s' % x/y)
except:
    print('Someting went wrong!')

>> Someting went wrong!

Для того, чтобы в случае ошибки вывести причину ее возникновения, нужно ее перехватить.

x = input('first number: ')
y = input('second number: ')
try:
    print('is: %s' % x/y)
except Exception as e:
    print(e)

>>> unsupported operand type(s) for /: 'str' and 'int'

Как определить тип исключения и принять решение, исходя из этого типа?

Каждое исключение имеет тип и мы можем его использовать.

try:
    print 'is: %s' % x/y
except TypeError:
    print 'is: %s' % str(x/y)
except ZeroDivisionError:
    print 'ZeroDivisionError exception!'

TypeError и ZeroDivisionError - это встроенные типы исключений и не требуют их импорта.

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

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

Для этого используем finally оператор.

Оператор finally.

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

try:
    print ('is: %s' % x/y)
except TypeError:
    print ('is: %s' % str(x/y))
except ZeroDivisionError:
    print ('ZeroDivisionError exception!')
finally:
    print('Finally block fired!')

>>>
code$ python exeption.py 
first number: 12
second number: 3
unsupported operand type(s) for /: 'str' and 'int'
is: 4
Finally block fired!

Кроме встроенных в python исключений мы можем создавать свои собственные, чтобы иметь возможность их отработать в клиентском коде.

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

Для этого нужно иметь возможность искусственно сгенерировать исключение в программе исходя из бизнес-логики.

Это делает оператор rase, который возвращает строку, или строковое представление объекта класса исключения.

В нашем случае это будет выглядить так:

raise AddMoneyError(1000)

Создадим такое исключение.

class AddMoneyError(Exception):
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return repr('User can not add more than %s' % self.value)

Мы создали свой класс исключения и унаследовались от python класса Exception.

Так же определили метод str где вывели описание ошибки используя внутреннюю переменную value для ее форматирования.

class User(object):
    account = 0
    def add(self,amount):
        if amount>1000:
            raise AddMoneyError(1000)
        else:
            self.account = self.account+amount

В клиентском коде попробуем пополнить счет.

user = User()
user.add(10000)
print 'finish operation'

Получаем

raise AddMoneyError(1000)
__main__.AddMoneyError: 'User can not add more than 1000'

Наше исключение сработало и мы можем его обработать.

user = User()
try:
    user.add(10000)
except AddMoneyError as e:
    print e


zdimon@dell:~/www/lyceum/8/code$ python limit_account.py
'User can not add more than 1000'
finish operation
zdimon@dell:~/www/lyceum/8/code$

Other topics