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

Ruby 예외

예외와 실행은 항상 함께 연결됩니다. 파일을 열었는데 파일이 없는 경우 적절히 처리하지 않으면 프로그램은 저질 프로그램으로 간주됩니다.

예외가 발생하면 프로그램이 중지됩니다. 예외는 프로그램 실행 중 발생할 수 있는 여러 유형의 오류를 처리하는 데 사용되며, 따라서 프로그램이 완전히 중지되지 않도록 적절한 조치를 취해야 합니다.

Ruby는 예외를 처리하는 완벽한 메커니즘을 제공합니다. 우리는 begin/end 블록에 예외를 던질 수 있는 코드를 추가하고, rescue 문장은 Ruby가 처리해야 할 예외 유형을 알립니다.

문법

begin #시작
 
 raise #예외를 던집니다
 
rescue [ExceptionType = StandardException] #지정된 유형의 예외를 잡습니다. 기본 값은 StandardException입니다
 $! #예외 정보를 나타냅니다
 $@ #예외가 발생한 코드 위치를 나타냅니다
else #기타 예외
 ...
ensure # 예외가 있与否에 관계없이 이 코드 블록에 진입
 
end # 끝

로 전달됩니다 begin 로 전달됩니다 rescue 중的一切는 보호됩니다. 코드 블록이 실행 중에 예외가 발생하면, 제어가 rescueend 블록.

사이의 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의 처음으로 이동합니다.

  • 이번에는 파일이 성공적으로 열렸습니다.

  • 기본 과정을 계속합니다.

주의:rename된 파일이 존재하지 않으면, 이 예제 코드는 무한히 시도합니다. 따라서 예외 처리 시 주의하십시오. retry.

사용하여 raise 문장

이를 사용할 수 있습니다 raise 문장이 예외를 퍼뜨립니다. 호출할 때 예외를 퍼뜨리는 이 메서드는 두 번째 메시지가 출력됩니다.

문법

raise 
 
또는
 
raise "Error Message" 
 
또는
 
raise ExceptionType, "Error Message"
 
또는
 
raise ExceptionType, "Error Message" condition

첫 번째 형식은 현재 예외를 단순히 다시 퍼뜨립니다. (현재 예외가 없으면 RuntimeError를 퍼뜨립니다). 이는 예외를 설명해야 하는 예외 처리 프로그램에 사용됩니다.

두 번째 형식은 새로운 RuntimeError 예외를 설정하고, 해당 문자열로 메시지를 설정합니다. 이 예외는 호출 스택으로 퍼뜨립니다.

세 번째 형식은 첫 번째 매개변수를 사용하여 예외를 생성하고, 두 번째 매개변수로 관련 메시지를 설정합니다.

네 번째 형식은 세 번째 형식과 유사하며, 추가 조건 문장(예:)} 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 "execution을 보장하십시오"
end

위 예제의 실행 결과는 다음과 같습니다:

A test exception.
["main.rb:4"]
execution을 보장하십시오

사용하여 else 문장

제공되면 else ensure 문장은 일반적으로 rescue ensure 문 이후, 어떤 문장이든 ensure 이전.

else ensure 문은 코드 본문이 예외를 발생시키지 않았을 때만 실행되는 문장의 주체입니다.

문법

begin 
   #.. 과정 
   #.. 예외를 발생시킵니다
rescue 
   #.. 오류를 처리합니다
else
   #.. 예외가 없으면 실행됩니다
ensure 
   #.. 마지막으로 실행을 보장합니다
   #.. 이는 항상 실행됩니다
end

온라인 예제

begin
 # 'A test exception.'를 발생시키십시오
 puts "저는 예외를 발생시키지 않습니다"
rescue Exception => e
  puts e.message
  puts e.backtrace.inspect
else
   puts "축하합니다"-- 에러가 없습니다"
ensure
  puts "execution을 보장하십시오"
end

위 예제의 실행 결과는 다음과 같습니다:

异常을 발생시키지 않습니다
축하합니다-- 에러가 없습니다!
execution을 보장하십시오

$! 변수를 사용하여 투げ쳐진 오류 메시지를 캡처할 수 있습니다.

Catch와 Throw

raise와 rescue의 예외 메커니즘은 오류가 발생할 때 실행을 포기할 수 있으며, 때로는 정상 처리 중에 깊은 내부 구조에서 벗어나야 할 때 있습니다. 이때 catch와 throw이 유용하게 사용됩니다.

catch 이는 주어진 이름(시μβ올이나 문자열이 될 수 있습니다)을 태그로 사용하는 블록을 정의합니다. 블록은 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
   res == "!"면 throw :quitRequested
   return res
end
 
catch :quitRequested do
   name = promptAndGet("Name: ")
   age = promptAndGet("Age: ")
   sex = promptAndGet("Sex: ")
   # ..
   # 처리 정보
end
promptAndGet("Name:")

위의 프로그램은 인공적인 상호작용이 필요하며, 여러분의 컴퓨터에서 시도할 수 있습니다. 이 예제의 실행 결과는 다음과 같습니다:

Name: Ruby on Rails
Age: 3
Sex: !
Name: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의 새로운 예제에 전달하여 특정한 예외로 인해 데이터 쓰기 실패가 발생했습니다.