Обработка исключений
| English | Русский |
|---|---|
| exception/ekˈsepʃn/ | исключение |
| exception handling/ekˈsepʃn ˈhændlɪŋ/ | обработка исключений |
| raise/reɪz/ | повышают |
Проверка, которую невозможно записать кодом
- Программа открывает файл. Перед открытием вы могли бы проверить, существует ли файл, доступен ли он для чтения, подключен ли диск. Предположим, каждая проверка прошла успешно.
- Между последней проверкой и открытием пользователь извлекает USB-накопитель. Файл существовал, когда вы спрашивали, и не существует, когда вы пытаетесь его открыть, и никакое предварительное тестирование не могло устранить этот разрыв.
- Некоторые ошибки просто невозможно предотвратить, потому что мир меняется между проверкой и действием. Что может сделать программа — так это реагировать на них, когда они происходят.
- Этот урок посвящен исключению, структуре TRY, которая обрабатывает одно, и тому, где в программе следует перехватывать исключение.
Что такое исключение и зачем его обрабатывать
- Исключение — это ошибка, возникающая во время выполнения: деление на ноль, файл не найден, неверный ввод, ушедшая сеть.
- Обработка исключений позволяет программе обнаружить ошибку и отреагировать на нее контролируемым образом, вместо того чтобы аварийно завершиться и потерять работу пользователя.
- Реальные программы сталкиваются с ошибками, которые нельзя предотвратить заранее, как показывает пример. И без исключений каждая отдельная операция потребовала бы собственной проверки
IFвокруг себя, зарывая реальный алгоритм в тесты ошибок. - Третье преимущество — это именно то, о чем чаще всего спрашивают на экзамене: оно разделяет нормальный поток выполнения и обработку ошибок, благодаря чему основной путь читается легко.
Исключение — это:
Исключения — это проблемы времени выполнения (деление на ноль, файл не найден), с помощью обработки которых можно реагировать на них корректно.
Почему следует использовать обработку исключений вместо проверки каждой ошибки заранее? Выберите все подходящие варианты.
Преимущества заключаются в правильности и понятности. Скорость не входит в их число; обработка добавляет небольшой накладные расходы, которые оправданы.
Структура TRY
TRY
OPENFILE "data.txt" FOR READ
READFILE "data.txt", line
CLOSEFILE "data.txt"
EXCEPT FileNotFound
OUTPUT "Sorry, the file does not exist."
EXCEPT ReadError
OUTPUT "Sorry, there was an error reading the file."
FINALLY
OUTPUT "Finished attempting to read."
ENDTRY
- Блок TRY содержит код, который может вызвать ошибку. Если он выполняется без сбоев, блоки EXCEPT полностью пропускаются.
- Если происходит исключение, выполнение немедленно переходит к первому подходящему блоку EXCEPT. Остальная часть блока TRY не выполняется.
- Блок FINALLY выполняется в любом случае, независимо от того, произошло ли исключение, что делает его идеальным местом для очистки, например, закрытия файла.

Один путь, когда всё хорошо, другой — когда нет, и один, который выполняется всегда
Как протекает обработка исключений
Разберите по шагам, что происходит при ошибке в коде. Исключение跳出 нормального потока к обработчику, FINALLY выполняет очистку в любом случае, и программа продолжает работу вместо того, чтобы аварийно завершиться.
Сопоставьте каждый ключевое слово для обработки исключений с его функцией.
TRY защищает рискованный код, EXCEPT перехватывает исключения, FINALLY выполняет очистку в любом случае, RAISE выбрасывает ошибку для последующего перехвата.
Блок FINALLY:
FINALLY всегда выполняется, поэтому идеально подходит для очистки, например, закрытия файлов.
Блок, который выполняется независимо от того, произошло ли исключение, что делает его идеальным для закрытия файлов, — это ____.
Очистка должна происходить на обоих путях. Размещение CLOSEFILE только в блоке TRY означает, что он будет пропущен именно тогда, когда ошибка оставила файл открытым.
Разобранный пример: проследите за потоком
- В коде выше файл не существует. Точно укажите, что будет выведено и что будет пропущено.
OPENFILEвызывает FileNotFound, поэтому выполнение покидает блок TRY немедленно: строкиREADFILEиCLOSEFILEникогда не выполняются.- Выполняется блок EXCEPT
FileNotFound, выводя «Sorry, the file does not exist». БлокReadErrorне выполняется, так как используется только первый подходящий обработчик. - Выполняется блок FINALLY, выводя «Finished attempting to read.»
- Самая частая ошибка — не заметить, что остальная часть блока TRY отбрасывается.
Файл в блоке TRY не существует. Расположите события в правильном порядке.
Выполняется только первый подходящий обработчик, а FINALLY выполняется в любом случае. Пропущенная оставшаяся часть блока TRY — это момент, который чаще всего упускают из виду.
Вызов исключения
- Подпрограмма, обнаружившая проблему, с которой она не может разумно справиться, может вызвать исключение, передавая ответственность тому, кто её вызвал:
IF b = 0 THEN RAISE DivideByZero
- Это правильное решение, когда подпрограмма знает, что что-то не так, но не знает, что следует сделать. Функция деления знает, что делитель равен нулю; только вызывающий код решает, спросить пользователя снова, использовать значение по умолчанию или отказаться от вычисления.
Подпрограмма использует RAISE для:
RAISE выбрасывает исключение вверх по цепочке вызовов, которое может быть перехвачено с помощью EXCEPT.
Почему подпрограмма деления должна выбрасывать исключение вместо самостоятельной обработки деления на ноль?
Запросить ввод заново, использовать значение по умолчанию или отказаться от вычислений: только вызывающий код обладает контекстом для выбора.
Где обрабатывать
- Обрабатывайте исключение близко к месту его возникновения, если реакция простая и локальная: вывести сообщение, использовать значение по умолчанию, попросить пользователя попробовать снова.
- Обрабатывайте его выше, если решение должно принимать более крупная часть программы: отказаться от всей транзакции, откатить изменения или сообщить пользователю, что операция не удалась.
- Золотое правило: ловите исключение на том уровне, где достаточно информации, чтобы решить, что делать, а не на том уровне, где оно было замечено в первую очередь.
Разобранный пример: чего не следует делать
- Студент оборачивает весь programme кодом в
EXCEPT: (do nothing), чтобы он никогда не падал. Объясните, почему это плохая практика. - Исключение поглощается: программа продолжает работать, как будто ничего не случилось, поэтому она работает с отсутствующими или недействительными данными и дает неправильные результаты вместо очевидного сбоя.
- Неочевидный сбой труднее диагностировать, чем краш, потому что нет сообщения и нет указания, где он произошел.
- Ловля каждого исключения в одном месте также означает потерю конкретного типа ошибки, поэтому невозможно выбрать разумную реакцию. Обработчик должен ловить конкретное исключение и действительно реагировать на него.
Молчаливое «поглощение» исключения (перехват, но отсутствие действий) скрывает реальные ошибки и затрудняет отладку — следует обрабатывать его или хотя бы записывать в лог.
Пустой обработчик скрывает именно те проблемы, которые нужно найти; всегда следует реагировать или фиксировать ошибку.
Потерянные баллы
- При возникновении исключения остальная часть блока TRY пропускается. Указывайте об этом при отслеживании потока.
- Выполняется только первый подходящий EXCEPT, а не все из них.
- FINALLY всегда выполняется, есть ошибка или нет, именно поэтому он подходит для закрытия файлов.
- Не ловите исключение и ничего не делайте. Поглощенная ошибка хуже, чем краш, потому что программа продолжает работу с плохими данными.
Вы поняли
- исключение — это ошибка во время выполнения; обработка позволяет программе реагировать вместо краша, покрывает ошибки, которые нельзя предотвратить заранее, и разделяет нормальный код и обработку ошибок
- TRY содержит рискованный код; при ошибке остальная часть пропускается, и выполняется первый подходящий EXCEPT; FINALLY выполняется в обоих случаях, поэтому очистка должна быть там
- подпрограмма, которая не может решить ответ, должна ВЫЗВАТЬ исключение для своего вызывающего кода
- обрабатывайте рядом для простой локальной реакции, выше, когда решение требует более широкого обзора; никогда не ловите и не делайте ничего