수색…


기본 오류 처리 블록

두 숫자를 나눌 함수를 만들자. 입력에 대해 매우 신뢰하고있다.

def divide(x, y)
  return x/y
end

이것은 많은 입력에 대해 잘 작동합니다.

> puts divide(10, 2)
5

전부는 아니지만

> puts divide(10, 0)
ZeroDivisionError: divided by 0

> puts divide(10, 'a')
TypeError: String can't be coerced into Fixnum

begin... end 블록에서 위험한 나누기 연산을 래핑하여 오류를 검사하고 rescue 절을 사용하여 메시지를 출력하고 문제가있는 경우 nil 반환하여 함수를 다시 작성할 수 있습니다.

def divide(x, y)
  begin
    return x/y
  rescue
    puts "There was an error"
    return nil
  end
end

> puts divide(10, 0)
There was an error

> puts divide(10, 'a')
There was an error

오류 저장

rescue 절에서 오류를 사용하려면 오류를 저장할 수 있습니다.

def divide(x, y)
  begin
    x/y
  rescue => e
    puts "There was a %s (%s)" % [e.class, e.message]
    puts e.backtrace
  end
end

> divide(10, 0)
There was a ZeroDivisionError (divided by 0)
       from (irb):10:in `/'
       from (irb):10
       from /Users/username/.rbenv/versions/2.3.1/bin/irb:11:in `<main>'

> divide(10, 'a')
There was a TypeError (String can't be coerced into Fixnum)
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb/workspace.rb:87:in `eval'
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb/workspace.rb:87:in `evaluate'
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb/context.rb:380:in `evaluate'
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb.rb:489:in `block (2 levels) in eval_input'
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb.rb:623:in `signal_status'
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb.rb:486:in `block in eval_input'
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb/ruby-lex.rb:246:in `block (2 levels) in each_top_level_statement'
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb/ruby-lex.rb:232:in `loop'
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb/ruby-lex.rb:232:in `block in each_top_level_statement'
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb/ruby-lex.rb:231:in `catch'
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb/ruby-lex.rb:231:in `each_top_level_statement'
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb.rb:485:in `eval_input'
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb.rb:395:in `block in start'
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb.rb:394:in `catch'
/Users/username/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb.rb:394:in `start'
/Users/username/.rbenv/versions/2.3.1/bin/irb:11:in `<main>'

다른 오류 확인하기

오류의 종류에 따라 다른 작업을 수행하려면 각각 다른 오류 유형의 인수로 여러 rescue 사용하십시오.

def divide(x, y)
  begin
    return x/y
  rescue ZeroDivisionError
    puts "Don't divide by zero!"
    return nil
  rescue TypeError
    puts "Division only works on numbers!"
    return nil
  end
end

> divide(10, 0)
Don't divide by zero!

> divide(10, 'a')
Division only works on numbers!

rescue 블록에서 사용하기 위해 오류를 저장하려면 다음을 수행하십시오.

rescue ZeroDivisionError => e

다른 rescue 절에 지정되지 않은 유형의 오류를 catch하려면 인수없이 rescue 절을 사용하십시오.

def divide(x, y)
  begin
    return x/y
  rescue ZeroDivisionError
    puts "Don't divide by zero!"
    return nil
  rescue TypeError
    puts "Division only works on numbers!"
    return nil
  rescue => e
    puts "Don't do that (%s)" % [e.class]
    return nil
  end
end

> divide(nil, 2)
Don't do that (NoMethodError)

이 경우 nil 을 2로 나눌 때는 ZeroDivisionError 또는 TypeError 가 아니므로 기본 rescue 절에 의해 처리됩니다.이 rescue 절은 NoMethodError 임을 알리는 메시지를 출력합니다.

재 시도 중

rescue 절에서 retry 를 사용하여 오류를 일으킨 상황을 변경 한 후 begin 절을 다시 실행할 수 있습니다.

def divide(x, y)
  begin
    puts "About to divide..."
    return x/y
  rescue ZeroDivisionError
    puts "Don't divide by zero!"
    y = 1
    retry
  rescue TypeError
    puts "Division only works on numbers!"
    return nil
  rescue => e
    puts "Don't do that (%s)" % [e.class]
    return nil
  end
end

TypeError 가 발생하는 것으로 TypeError 매개 변수를 전달하면 begin 절이 실행되고 ( "약 나누기"를 인쇄하여 여기에 플래그가 TypeError ) 오류가 이전과 같이 catch되고 nil 이 반환됩니다.

> divide(10, 'a')
About to divide...
Division only works on numbers!
 => nil

그러나 ZeroDivisionError 를 유발할 매개 변수를 전달하면 begin 절이 실행되고 오류가 감지되고 제수가 0에서 1로 변경된 다음 retry 하면 begin 블록이 다시 실행됩니다 (위에서부터). 다른 y . 두 번째로는 오류가 없으며 함수는 값을 반환합니다.

> divide(10, 0)
About to divide...     # First time, 10 ÷ 0
Don't divide by zero!
About to divide...     # Second time 10 ÷ 1
=> 10

오류 발생 여부 확인

에러가 발생하지 않으면 실행될 코드에 else 절을 사용할 수 있습니다.

def divide(x, y)
  begin
    z = x/y
  rescue ZeroDivisionError
    puts "Don't divide by zero!"
  rescue TypeError
    puts "Division only works on numbers!"
    return nil
  rescue => e
    puts "Don't do that (%s)" % [e.class]
    return nil
  else
    puts "This code will run if there is no error."
    return z
  end
end

제어를 rescue 절 중 하나로 전달하는 오류가있는 경우 else 절은 실행되지 않습니다.

> divide(10,0)
Don't divide by zero!
=> nil

그러나 오류가 발생하지 else 절이 실행됩니다.

> divide(10,2)
This code will run if there is no error.
=> 5

begin 절에서 돌아 오면 else 절은 실행되지 않습니다.

def divide(x, y)
  begin
    z = x/y
    return z                 # Will keep the else clause from running!
  rescue ZeroDivisionError
    puts "Don't divide by zero!"
  else
    puts "This code will run if there is no error."
    return z
  end
end

> divide(10,2)
=> 5

항상 실행해야하는 코드

항상 실행하려는 코드가있는 경우, ensure 절을 사용하십시오.

def divide(x, y)
  begin
    z = x/y
    return z
  rescue ZeroDivisionError
    puts "Don't divide by zero!"
  rescue TypeError
    puts "Division only works on numbers!"
    return nil
  rescue => e
    puts "Don't do that (%s)" % [e.class]
    return nil
  ensure
    puts "This code ALWAYS runs."
  end
end

오류가있을 때 ensure 절이 실행됩니다.

> divide(10, 0)
Don't divide by zero!   # rescue clause
This code ALWAYS runs.   # ensure clause
=> nil

그리고 오류가없는 경우 :

> divide(10, 2)
This code ALWAYS runs.   # ensure clause
=> 5

확실한 절은 파일이 닫혀 있는지 확인하고자 할 때 유용합니다.

else 절과 달리 ensure begin 또는 rescue 절이 값을 반환하기 전에 실행 begin . 는 IF ensure 절은이 return 무시됩니다 return 다른 조항의 가치를!



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow