_ruby異常

8058 ワード

Ruby異常
例外と実行は常に関連付けられています.存在しないファイルを開き、適切に処理していない場合は、プログラムは低品質とみなされます.
異常が発生した場合、プログラムは停止します.例外は、プログラムの実行中に発生する可能性のあるさまざまなタイプのエラーを処理するために使用されます.プログラムを完全に停止させることなく、適切な行動を取らなければなりません.
Rubyは異常を完璧に処理するメカニズムを提供した.begin/endブロックに異常を投げ出す可能性のあるコードを添付し,rescue句を用いてRubyに処理すべき異常タイプを完全に伝えることができる.
構文
begin  
# -  
rescue OneTypeOfException  
# -  
rescue AnotherTypeOfException  
# -  
else  
#     
ensure
#      
end
 

beginからrescueまでのすべては保護されています.コードブロックの実行中に異常が発生した場合、制御はrescueとendの間のブロックに渡されます.
beginブロック内の各rescue句について,Rubyは投げた異常を各パラメータと交互に比較した.rescue句に名前が付けられている例外が、現在投げ出されている例外タイプと同じか、またはその例外の親である場合、一致は成功します.
例外が指定したすべてのエラー・タイプに一致しない場合は、すべてのrescue句の後にelse句を使用できます.
≪インスタンス|Instance|emdw≫
#!/usr/bin/ruby

begin
   file = open("/unexistant_file")
   if file
      puts "File opened successfully"
   end
rescue
      file = STDIN
end
print file, "==", STDIN, "
"
 

これにより、以下の結果が得られます.開くのに失敗したため、stdINがfileに取って代わったことがわかります.
#<IO:0xb7d16f84>==#<IO:0xb7d16f84>
 

retry文の使用
rescueブロックを使用して例外をキャプチャし、retry文を使用して最初からbeginブロックを実行できます.
構文
begin
    #                rescue     
rescue
    #              
    retry  #         begin    
end
 

≪インスタンス|Instance|emdw≫
#!/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文を使用して例外を放出できます.次の方法では、呼び出し時に例外を放出します.2番目のメッセージが出力されます.
    構文
    raise 
    
    OR
    
    raise "Error Message" 
    
    OR
    
    raise ExceptionType, "Error Message"
    
    OR
    
    raise ExceptionType, "Error Message" condition
    
     

    第1の形態は、現在の異常を単純に再放出する(現在の異常がなければRuntimeErrorを放出する).これは、異常が入力される前に異常を説明する必要がある異常ハンドラで使用されます.
    2つ目の形式は、指定された文字列にメッセージを設定する新しいRuntimeError例外を作成します.この例外は、呼び出しスタックに放出されます.
    第3の形式では、第1のパラメータを使用して例外を作成し、関連するメッセージを第2のパラメータに設定します.
    4番目の形式は3番目の形式と似ています.unlessなどの追加の条件文を追加して例外を投げ出すことができます.
    ≪インスタンス|Instance|emdw≫
    #!/usr/bin/ruby
    
    begin  
        puts 'I am before the raise.'  
        raise 'An error has occurred.'  
        puts 'I am after the raise.'  
    rescue  
        puts 'I am rescued.'  
    end  
    puts 'I am after the begin block.'
     

    これにより、次の結果が得られます.
    I am before the raise.  
    I am rescued.  
    I am after the begin block.
     

    もう1つの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
    
     

    ≪インスタンス|Instance|emdw≫
    begin
      raise 'A test exception.'
    rescue Exception => e
      puts e.message
      puts e.backtrace.inspect
    ensure
      puts "Ensuring execution"
    end
    
     

    これにより、次の結果が得られます.
    A test exception.
    ["main.rb:4"]
    Ensuring execution
    
     

    else文の使用
    else句が提供される場合、通常はrescue句の後、任意のensureの前に配置されます.
    else句の主体は,コード主体が異常を投げ出さなかった場合にのみ実行される.
    構文
    begin 
       #..    
       #..     
    rescue 
       #..     
    else
       #..          
    ensure 
       #..       
       #..       
    end
    
     

    ≪インスタンス|Instance|emdw≫
    begin
     #    'A test exception.'
     puts "I'm not raising exception"
    rescue Exception => e
      puts e.message
      puts e.backtrace.inspect
    else
       puts "Congratulations-- no errors!"
    ensure
      puts "Ensuring execution"
    end
    
     

    これにより、次の結果が得られます.
    I'm not raising exception
    Congratulations-- no errors!
    Ensuring execution
    
     

    $を使用!変数は、投げ出されたエラーメッセージをキャプチャします.
    CatchとThrow
    raiseとrescueの異常メカニズムは、エラーが発生したときに実行を放棄することができ、通常の処理時に深いネストされた構造から飛び出す必要がある場合があります.このときcatchとthrowが役に立ちます.
    catchは、指定された名前(SymbolまたはString)をラベルとして使用するブロックを定義します.ブロックは正常に実行され、throwに遭遇したことを知っています.
    構文
    throw :lablename
    #..       
    catch :lablename do
    #..       throw          catch
    end
    
    OR
    
    throw :lablename condition
    #..       
    catch :lablename do
    #..       throw          catch
    end
    
     

    ≪インスタンス|Instance|emdw≫
    次の例では、ユーザーが「!任意のプロンプトに応答して、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:")
    
     

    上記のプログラムは人工的なインタラクションが必要で、コンピュータで試してみることができます.これにより、次の結果が得られます.
    Name: Ruby on Rails
    Age: 3
    Sex: !
    Name:Just Ruby
    
     

    クラスException
    Rubyの標準クラスとモジュールから例外が放出されます.すべての例外クラスは、上部のExceptionクラスを含む階層を構成します.次の階層は7つの異なるタイプです.
  • 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の新しいインスタンスに伝え、特定の異常によってデータの書き込みに失敗した.