Обработка исключений относится к процессу прогнозирования и определения способов обработки ошибок, возникающих в программе во время выполнения. Ошибка в большинстве случаев относится к неожиданному событию или возникновению во время выполнения программы. Например, ошибка может возникнуть при чтении файла либо из-за того, что файл не существует, либо из-за того, что у пользователя нет прав на чтение или запись в файл.
Из этого туториала Вы узнаете, как реализовать обработку исключений в Ruby с помощью блоков повышения и восстановления.
Основное использование
Большинство языков программирования реализуют обработку исключений с помощью блока try и catch. Однако, как и все остальное в Ruby, ключевые слова более информативны.
Мы можем выразить общий синтаксис, как показано ниже:
begin
raiseexception
# raise ecxeption
rescue exception
# rescue block
end
Мы заключаем блок обработки исключений в операторы начала и конца. Внутри этих операторов мы определяем блоки повышения и восстановления.
В повышении мы определяем исключение, которое мы можем вызвать вручную или попросить интерпретатора Ruby сгенерировать его. По умолчанию параметром для блока повышения является RuntimeError.
Далее идет спасательный блок. Как следует из названия, этот блок приходит на помощь при возникновении исключения. Он контролирует выполнение программы.
Ruby сравнивает исключение, вызванное блоком повышения, с параметрами, переданными в блок восстановления. Если исключение относится к тому же типу или суперклассу, оно запускает блок восстановления.
Пример обработки исключений в Ruby
Мы можем реализовать простой пример, чтобы проиллюстрировать, как работает обработка исключений в Ruby:
def err_me
begin
puts «Hi there!»
raise «string type»
rescue
puts «Never mind, I am fixed!»
end
end
err_me
В приведенном выше примере мы определяем функцию с блоком исключения.
Мы вручную вызываем исключение, которое прерывает выполнение программы и входит в блок восстановления. Это выполняет действия в блоке — в данном случае оператор put и завершает работу.
Если вы добавляете какой-либо блок кода сразу после повышения и перед блоком восстановления, они не выполняются, потому что блок восстановления немедленно обрабатывает поток программы.
По умолчанию блок восстановления использует параметр StandardError. Однако в Ruby есть и другие типы ошибок, в том числе.
- SyntaxError
- IOError
- RegexpError
- ThreadError
- ZeroDivisionError
- NoMethodError
- IndexError
- NameError
- TypeError
Чтобы вызвать и обработать конкретный тип ошибки, мы можем передать ее блоку повышения в качестве параметра. Вот пример:
begin
raiseZeroDivisionError
rescue =>exception
puts exception.message
puts exception.backtrace.inspect
end
В приведенном выше примере мы вызываем ошибку ZeroDivisionError. Затем мы переходим к блоку восстановления, который печатает конкретный тип исключения и отслеживает источник.
Результат:
$ ruby err—handling.rb
ZeroDivisionError
[«err-handling.rb:2:in `<main>'»]
Другие блоки исключений
Помимо основного блока повышения и восстановления, Ruby также предоставляет нам другие блоки, которые мы можем реализовать для обработки ошибок.
Блокировка повтора
Блок повтора используется для повторного запуска блока восстановления после возникновения исключения. Вот пример:
begin
raise ZeroDivisionError
puts «I don’t run 😢»
rescue => exception
puts «#{exception.message} caused me to die ⚰️»
retry
end
Если мы запустим приведенный выше код, он распечатает сообщение внутри блока восстановления. Он встретит блок повтора, который переходит в блок восстановления.
Распространенный вариант использования блоков повтора — поиск ошибок с помощью грубой силы. Примером может служить повторная загрузка страницы при отсутствии соединения до тех пор, пока ошибка не будет устранена.
ВНИМАНИЕ: будьте осторожны при использовании блока повтора, поскольку он является обычным источником бесконечных циклов.
Обеспечить блокировку
Если вы программировали на другом языке, таком как Python, вы, вероятно, знакомы с блоком finally. Блок обеспечения в Ruby работает аналогично блоку finally в других языках программирования.
Блок обеспечения всегда запускается в конце кода. Независимо от того, правильно ли было обработано возникшее исключение или завершено выполнение программы, оно всегда запускается или выполняется.
Вот пример:
begin
raise ZeroDivisionError
puts «I don’t run 😢»
rescue => exception
puts «#{exception.message} caused me to die ⚰️»
ensure
puts «I will always run 🚀»
end
В этом случае приведенный выше код напечатает сообщение об исключении и, наконец, запустит блок обеспечения.
ZeroDivisionError caused me to die ⚰️
I will always run 🚀
Else блок
Если исключение не возникает, мы можем реализовать блок для выполнения действия с помощью оператора else.
Например:
begin
rescue => exception
puts «#{exception.message} caused me to die ⚰️»
else
puts «Trust me, I ran successfully 😀»
ensure
puts «& I will always run 🚀»
end
Блок else помещается между блоками rescue и protect. В приведенном выше примере вы заметите, что отсутствует блок повышения, что приводит к запуску блока else.
Вот пример вывода:
Поверьте мне, я успешно провел 😀
& I will always run 🚀
Легкая обработка исключений
Блоки повышения и восстановления — удобный способ выполнить действие при возникновении ошибки. Однако, поскольку обработка ошибок создает трассировку стека для облегчения отладки, это может легко стать проблемой в вашей программе. Вот тут-то и пригодятся блоки для ловли и броска.
Чтобы реализовать блок catch-throw, вы начинаете с определения метки с помощью ключевого слова catch. Как только Ruby встречает блок throw, который ссылается на блок catch, он останавливает выполнение и переходит к блоку catch.
Давайте использовать пример, чтобы проиллюстрировать эту концепцию. Рассмотрим беспорядочное вложение, показанное в приведенном ниже коде:
catch(:kill_me_now) do
langs = [«Python», «Ruby», «C++», «C#»]
foriinlangsdo
for index in 1..5
if index == 3
ifi == «C#»
puts «After throw, nothing will run!'»
throw(:kill_me_now)
puts «I am C#»
end
end
end
end
end
puts «Oh boy! That was a long one!»
Мы начинаем с использования ключевого слова catch и передаем метку внутри пары круглых скобок. Как только мы запустим код, он выполнит все вложенные циклы и операторы if, пока не встретит оператор throw, ссылающийся на catch.
Это немедленно прекратит выполнение и вернется на уровень оператора catch.
Вот пример вывода:
After throw, nothing will run!‘
Oh boy! That was a long one!
Заключение
В этом руководстве показано, как реализовать обработку ошибок в Ruby с помощью блоков повышения и восстановления.