Шаг 152.
Основы языка Python.
Обработка исключений. Пользовательские исключения

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

    Для возбуждения пользовательских исключений предназначены две инструкции:

    Инструкция raise возбуждает заданное исключение. Она имеет несколько вариантов формата:

  raise <Экземпляр класса>
  raise <Название класса>
  raise <Экземпляр или название класса> from <Объект исключения>
  raise

    В первом варианте формата инструкции raise указывается экземпляр класса возбуждаемого исключения. При создании экземпляра можно передать данные конструктору класса. Эти данные будут доступны через второй параметр в инструкции except. Пример возбуждения встроенного исключения ValueError:

>>> raise ValueError("Описание исключения")
Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    raise ValueError("Описание исключения")
ValueError: Описание исключения

    Пример обработки этого исключения:

>>> try:
  raise ("Описание исключения")
except ValueError as msg:
  print(msg) # Выведет: Описание исключения

  
Описание исключения

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

class MyError(Exception):
    def __init__ (self, value):
        self.msg = value
    def __str__(self):
        return self.msg
# Обработка пользовательского исключения
try:
    raise MyError("Описание исключения")
except MyError as err:
    print (err)     # Вызывается метод __str__()
    print (err.msg) # Обращение к атрибуту класса
# Повторно возбуждаем исключение 
raise MyError("Описание исключения")
Архив с файлом можно взять здесь.

    Результат выполнения:

Описание исключения
Описание исключения
Traceback (most recent call last):
  File "C:\Python34\Files\152_1.py", line 13, in 
    raise MyError("Описание исключения")
MyError: Описание исключения

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

class MyError(Exception): pass
try:
    raise MyError("Описание исключения")
except MyError as err:
    print (err)     # Выведет: Описание исключения
Архив с файлом можно взять здесь.

    Результат выполнения:

Описание исключения

    Во втором варианте формата инструкции raise в первом параметре задается объект класса, а не экземпляр. Пример;

>>> try:
  raise ValueError # Эквивалентно: raise ValueError()
except ValueError:
  print("Сообщение об ошибке")

  
Сообщение об ошибке

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

>>> try:
  x = 1 / 0
except Exception as err:
  raise ValueError() from err
Результат выполнения:
Traceback (most recent call last):
  File "<pyshell#20>", line 2, in <module>
    x = 1 / 0
ZeroDivisionError: division by zero

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<pyshell#20>", line 4, in <module>
    raise ValueError() from err
ValueError

    Как видно из результата, мы получили информацию не только по исключению ValueError, но и по исключению ZeroDivisionError. Следует заметить, что при отсутствии инструкции from информация сохраняется неявным образом. Если убрать инструкцию from в предыдущем примере, то получим следующий результат:

Traceback (most recent call last):
  File "<pyshell#22>", line 2, in <module>
    x = 1 / 0
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<pyshell#22>", line 4, in <module>
    raise ValueError()
ValueError

    Четвертый вариант формата инструкции raise позволяет повторно возбудить последнее исключение и обычно применяется в коде, следующем за инструкцией except. Пример:

class MyError(Exception): pass
try:
    raise MyError("Сообщение об ошибке")
except MyError as err:
    print (err)
    raise # Повторно возбуждаем исключение
Архив с файлом можно взять здесь.

    Результат выполнения:

Сообщение об ошибке
Traceback (most recent call last):
  File "C:\Python34\Files\152_3.py", line 3, in <module>
    raise MyError("Сообщение об ошибке")
MyError: Сообщение об ошибке

    Инструкция assert возбуждает исключение AssertionError, если логическое выражение возвращает значение False. Инструкция имеет следующий формат:

  assert  <Логическое  выражение> [, <Данные>]

    Инструкция assert эквивалентна следующему коду:

if __debug__:
    if not <Логическое  выражение>:
        raise AssertionError(<Данные>)

    Если при запуске программы используется флаг -O, то переменная __debug__ будет иметь ложное значение. Таким образом можно удалить все инструкции assert из байт-кода.

    Пример использования инструкции assert

try:
    x = -3
    assert x >= 0, "Сообщение об ошибке"
except AssertionError as err:
    print(err) # Выведет: Сообщение об ошибке
Архив с файлом можно взять здесь.

    Результат выполнения:

Сообщение об ошибке

    Со следующего шага мы начнем рассматривать классы итераторов, контейнеров и перечислений.




Предыдущий шаг Содержание Следующий шаг