English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Ruby 基础教程

Ruby 高级教程

Исключения Ruby

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

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

Ruby предоставляет совершенный механизм обработки исключений. Мы можем begin/end в блоке можно добавить код, который может вызвать исключение, и использовать rescue подразделение рассказывает Ruby, какие типы исключений нужно обработать.

Синтаксис

begin #开始
 
 raise.. #抛出异常
 
rescue [ExceptionType = StandardException] #捕获指定类型的异常默认值是 StandardException
 $! # указывает на информацию об исключении
 $@ # указывает на положение кода, где возникло исключение
else #其余的 исключения
 ..
ensure # неважно, есть ли исключение, вход в этот блок кода
 
end # конец

от begin к rescue всего в блоке. Если в процессе выполнения блока происходит исключение, управление передается rescue и end между

для begin каждый rescue пункт, Ruby сравнивает выброшенное исключение с каждым параметром. Если имя исключения в блоке rescue совпадает с типом текущего выброшенного исключения или является его суперклассом, то происходит успешное совпадение.

Если исключение не соответствует всем指定的 типам ошибок, мы можем использовать все rescue пункт. else пункт.

Онлайн пример

#!/usr/bin/ruby
 
begin
   file = open("/unexistant_file")
   if file
      puts "File opened successfully"
   end
rescue
      file = STDIN
end
print file, "==", STDIN, "\n"

Результат выполнения примера выше. Вы можете видеть,STDIN заменяет file поэтомуоткрытиенеудача.

#<IO:0xb7d16f84>==#<IO:0xb7d16f84>

используйте retry утверждение

Вы можете использовать rescue Блок перехватывает исключение и затем использует retry Сначала выполняется команда в блоке. begin блок.

Синтаксис

begin
    # Исключение, выброшенное этим кодом, будет перехвачено следующим блоком rescue
rescue
    # Этот блок будет перехватывать все типы исключений
    retry # Это вернет управление к началу begin
end

Онлайн пример

#!/usr/bin/ruby
 
begin
   file = open("/unexistant_file")
   if file
      puts "File opened successfully"
   end
rescue
   fname = "existant_file"
   retry
end

Вот процесс обработки:

  • Произошло исключение при открытии.

  • Перепрыгнуть к rescue. fname заново присваивается.

  • С помощью retry перепрыгнуть к началу begin.

  • В этот раз файл успешно открыт.

  • Продолжить базовый процесс.

Примечание:Если переназванный файл не существует, этот пример кода будет бесконечно пытаться. Поэтому при обработке исключений будьте осторожны. retry.

используйте raise утверждение

Вы можете использовать raise Эта команда выбрасывает исключение. Следующие методы выбрасывают исключение при вызове. Его второе сообщение будет выведено.

Синтаксис

raise 
 
или
 
raise "Error Message" 
 
или
 
raise ExceptionType, "Error Message"
 
или
 
raise ExceptionType, "Error Message" condition

Первый вид просто перебрасывает текущее исключение (если нет текущего исключения, выбрасывается RuntimeError). Это используется в обработчиках исключений, которые необходимо объяснить до передачи исключения.

Второй вид создает новый RuntimeError Исключение, устанавливающее его сообщение как заданную строку. Это исключение затем выбрасывается в呼叫ный стек.

Третий вид создает исключение с использованием первого параметра и устанавливает связанное сообщение как второй параметр.

Четвертый вид ähnlich dem dritten, вы можете добавить любые дополнительные условия (например unless)для выброса исключения.

Онлайн пример

#!/usr/bin/ruby
 
begin  
    puts 'Я перед raise.'  
    raise 'Произошла ошибка.'  
    puts 'Я после raise.'  
rescue  
    puts 'Я спасен.'  
end  
puts 'Я после блока begin.'

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

Я перед raise.  
Я спасен.  
Я после блока begin.

еще один пример raise Пример использования:

Онлайн пример

#!/usr/bin/ruby
 
begin  
  raise 'A test exception.'  
rescue Exception => e  
  puts e.message  
  puts e.backtrace.inspect  
end

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

A test exception.
["main.rb:4"]

используйте ensure утверждение

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

ensure Условие делает именно это. ensure размещается после последнего rescue и содержит блок кода, который всегда выполняется при завершении блока. Это независимо от того, был ли блок завершен нормально, выброшено и обработано исключение, или он был завершен из-за не捕获ленного исключения.ensure блок всегда выполняется.

Синтаксис

begin 
   #.. Процесс
   #.. Выбрасывает исключение
rescue 
   #.. Обработка ошибок 
ensure 
   #.. В конце убедитесь, что выполняется
   #.. Это всегда выполняется
end

Онлайн пример

begin
  raise 'A test exception.'
rescue Exception => e
  puts e.message
  puts e.backtrace.inspect
ensure
  puts "Обеспечение выполнения"
end

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

A test exception.
["main.rb:4"]
Обеспечение выполнения

используйте else утверждение

если предоставлен else условие, обычно放置 в rescue после условия, в любое время ensure ранее.

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

Синтаксис

begin 
   #.. Процесс 
   #.. Выбрасывает исключение
rescue 
   #.. Обработка ошибок
else
   #.. Если нет исключений, выполняется
ensure 
   #.. В конце убедитесь, что выполняется
   #.. Это всегда выполняется
end

Онлайн пример

begin
 # Выбрасывает 'A test exception.'
 puts "Я не поднимаю исключение"
rescue Exception => e
  puts e.message
  puts e.backtrace.inspect
else
   puts "Поздравляем -- нет ошибок!"
ensure
  puts "Обеспечение выполнения"
end

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

Я не поднимаю исключение
Поздравляем -- нет ошибок!
Обеспечение выполнения

Использование переменной $! позволяет捕获 сообщение об ошибке, которое было выброшено.

Catch и Throw

Механизмы raise и rescue позволяют прервать выполнение при возникновении ошибки, иногда необходимо跳出 некоторые глубоко вложенные структуры в процессе нормального обработки. В таких случаях catch и throw становятся полезными.

catch Определен блок, использующий заданное имя (будь то Symbol или String) в качестве тега. Блок выполняется до тех пор, пока не встретится throw.

Синтаксис

throw :lablename
#.. Это не будет выполнено
catch :lablename do
#.. После throw выполняется соответствующий catch
end
 
или
 
throw :lablename condition
#.. Это не будет выполнено
catch :lablename do
#.. После throw выполняется соответствующий catch
end

Онлайн пример

В следующем примере, если пользователь в ответ на любое提示 вводит '!', используется throw для завершения взаимодействия с пользователем.

Онлайн пример

def promptAndGet(prompt)
   print prompt
   res = readline.chomp
   throw :quitRequested if res == "!"
   return res
end
 
catch :quitRequested do
   name = promptAndGet("Name: ")
   age = promptAndGet("Age: ")
   sex = promptAndGet("Sex: ")
   # ..
   # Обработка информации
end
promptAndGet("Name:")

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

Имя: Ruby on Rails
Возраст: 3
Пол: !
Имя: Just Ruby

класс Exception

Стандартные классы и модули Ruby генерируют исключения. Все классы исключений образуют иерархию, включая верхний класс Exception. На следующем уровне семь различных типов:

  • Interrupt

  • NoMemoryError

  • SignalException

  • ScriptError

  • StandardError

  • SystemExit

Fatal - это еще одно исключение в этом слое, но интерпретатор Ruby использует его только внутренне.

ScriptError и StandardError имеют свои подклассы, но в данном случае нам не нужно знать эти детали. Самое важное - создать свои собственные классы исключений, они должны быть подклассами класса Exception или его потомками.

Давайте посмотрим на пример:

Онлайн пример

class FileSaveError < StandardError
   attr_reader :reason
   def initialize(reason)
      @reason = reason
   end
end

Теперь посмотрите на следующий пример, который использует上面的 исключение:

Онлайн пример

File.open(path, "w") do |file|
begin
    # Запись данных...
rescue
    # Ошибка
    raise FileSaveError.new($!)
end
end

Здесь最重要ая строка - raise FileSaveError.new($!)Мы вызываем raise, чтобы показать, что ошибка уже произошла, и передаем ее новому примеру FileSaveError, так как данные не могут быть записаны из-за определенной ошибки.