【Ruby入門】例外処理の使い方まとめ(begin・rescue・raise の使い方)

例外処理を用いることで、エラーが発生したときに行う処理を記述しておくことができます。

以下から Ruby の例外処理で用いる「begin・rescue・raise」の使い方を解説していきます。

メモ

そもそも例外処理とは何か? という解説はこちら

 

例外処理の基本

rescue の使い方

以下のように begin の下に、通常 実行したいプログラムを書きます。そのプログラムの実行中に例外が発生したときだけ呼び出したいコードを rescue の下に書きます。

begin
  実行するコード
rescue
  例外が発生したときだけ実行されるコード
end

 

また、else を付け加えることで、以下のように例外が発生しなかったときだけ呼び出したいコードを追加することができます。

begin
  実行するコード
rescue
  例外が発生したときだけ実行されるコード
else
  例外が発生しなかったときだけ実行されるコード
end

 

ensure の使い方

以下のように ensure を付け加えると、例外の有無に関わらず 最後に実行したいプログラムを追加できます。

begin
  実行するコード
rescue
  例外が発生したときだけ実行されるコード
else
  例外が発生しなかったときだけ実行されるコード
ensure
  例外の有無にかかわらず 最後に実行されるコード
end

 

raise の使い方

例外を意図的に起こしたい場合は、プログラム中で以下のように記述します。

raise

 

例外の種類を指定したい場合は、以下のように後ろにエラーの種類を記述します。

raise エラーの種類

 

例外処理を使ったプログラム例

実際にプログラムを書いて動作を確認してみましょう。

 

例外が発生したときだけ実行するコードを追加する(rescue の使用例)

以下は例外が発生したら「例外が発生しました」というメッセージを表示するプログラム。

数値を0で割る計算(1/0)はできないので例外となり、rescue の下にあるコードが実行されます。

プログラム
begin
  p 1/0
rescue
  p "例外が発生しました"
end
実行結果
"例外が発生しました"

 

例外が発生したときにエラー情報を取得する

rescue のあとに => 変数名 をつけることで、指定した変数名でエラー情報を取得することができます。

以下は「e」という変数名でエラー情報を取得する例。

プログラム
begin
  p 1/0
rescue => e
  p e
  p e.class # 例外の種類
  p e.message # 例外のメッセージ
  p e.backtrace # 例外が発生した位置情報
end
実行結果
#<ZeroDivisionError: divided by 0>
ZeroDivisionError
"divided by 0"
["test.rb:2:in `/'", "test.rb:2:in `<main>'"]

 

発生した例外の種類によって処理を変える

rescue のあとに例外の種類を指定することで、発生した例外の種類によって処理を変えることができます。

以下は「ZeroDivisionError」と、「NameError」または「RuntimeError」が発生したときで処理を変える例。

プログラム
begin
  p 1/0
rescue ZeroDivisionError
  p "エラー1"
rescue NameError, RuntimeError # 2つまとめて指定することもできる
  p "エラー2"
end
実行結果
"エラー1"

 

例外が発生しなかったときだけ実行するコードを追加する(else の使用例)

以下は上のプログラムに else を付け加えた例。

begin の下にあるコードに例外が発生しないので、else の下にあるコードが最後に実行されます。

プログラム
begin
  p "テスト"
rescue
  p "例外が発生しました"
else
  p "例外が発生しませんでした"
end
実行結果
"テスト"
"例外が発生しませんでした"

 

例外の有無に関わらず 最後に実行したいプログラムを追加する(ensure の使用例)

ensure を使うと、例外の有無に関係なく 最後に必ず実行したいコードを追加することができます。

 

以下は例外が発生しない場合の例。ensure の下にある p "プログラム終了" のコードが実行されます。

プログラム
begin
  p "テスト"
rescue
  p "例外が発生しました"
else
  p "例外が発生しませんでした"
ensure
  p "プログラム終了"
end
実行結果
"テスト"
"例外が発生しませんでした"
"プログラム終了

 

こちらは例外が発生した場合の例。こちらも ensure の下にある p "プログラム終了" のコードが実行されていることが確認できます。

プログラム
begin
  p 1/0
rescue
  p "例外が発生しました"
else
  p "例外が発生しませんでした"
ensure
  p "プログラム終了"
end
実行結果
"例外が発生しました"
"プログラム終了"

 

ensure の使い道として、例えばファイルを開いて作業を行うプログラムの場合、実行中に例外が発生してもしなくても、必ず最後にファイルを閉じておく、といったことができます。

f = File.open('test.txt') # ファイルを開く

begin
  # ファイルに対して行いたい処理
rescue
  # 例外が発生したときの処理
ensure
  f.close if f # ファイルを閉じる
end

 

意図的に例外を発生させる(raise の使用例)

以下は意図的に例外を発生させるプログラム例。

raise の行で例外が発生します。

プログラム
begin
  raise
rescue
  p "例外が発生しました"
end
実行結果
"例外が発生しました"

 

raise のあとに例外の種類を指定することもできます。

以下は「NameError」を発生させる例。

プログラム
begin
  raise NameError
rescue => e
  p "例外が発生しました"
  p e
end
実行結果
"例外が発生しました"
#<NameError: NameError>

 

例外のメッセージを指定することもできます。

以下は種類が「NameError」で、メッセージが「エラーのテスト」の例外を発生させる例。

プログラム
begin
  raise NameError, "例外のテスト"
rescue => e
  p "例外が発生しました"
  p e
end
実行結果
"例外が発生しました"
#<NameError: 例外のテスト>

 

以下のように、例外のメッセージのみを指定することもできます。その場合、例外の種類は「RuntimeError」となります。

プログラム
begin
  raise "例外のテスト"
rescue => e
  p "例外が発生しました"
  p e
end
実行結果
"例外が発生しました"
#<RuntimeError: 例外のテスト>

 

例外が発生したら、再度 処理をやり直す(retry の使用例)

retry を使うと、begin 以下に記述した処理を 再度やり直すことができます。

以下は例外が発生したら、3回まで処理をやり直す例。

プログラム
count = 0

begin
  raise
rescue
  count += 1
  p "処理失敗(#{count}回目)"
  if count < 3
    retry
  end

  p "プログラム終了"
end
実行結果
"処理失敗(1回目)"
"処理失敗(2回目)"
"処理失敗(3回目)"
"プログラム終了"

 

外部と通信するときに、接続に失敗したら再度 接続する、といった処理を記述するときに便利です。

 

メソッド全体に例外処理を設ける

メソッド全体に例外処理を設ける場合は、beginend を省略することができます。

以下のプログラムを例にしてみましょう。

def test
  begin
    p 1/0
  rescue
    p "例外が発生しました"
  end
end

 

上のプログラムは以下のように書くこともできます。記述を減らすことができ、階層を深くする必要がなくなります。

def test
  p 1/0
rescue
  p "例外が発生しました"
end
メモ

メソッドについて詳しくはこちら(作成中)。

メモ

あまり見かけませんが、メソッドだけでなくクラスの場合でも同様の形で記述することができます。

 

まとめ

以上、Rubyでの例外処理の使い方でした!

 

ここまでの内容をまとめておきます。

  • 例外処理は「begin … rescue … else … ensure … end」のように記述する。
  • begin の下に、通常 実行したいコードを書く。
  • rescue の下に、例外が起こったときに実行するコードを書く。
  • else の下に、例外が起こらなかったときだけ実行するコードを書く。
  • ensure の下に、例外の有無に関わらず 最後に実行したいコードを書く。
  • rescue => 変数名 のようにすると、指定した変数名でエラー情報を取得できる。
  • rescue 例外の種類 のようにすると、発生した例外の種類によって処理を変えることができる。
  • raise を使って、例外を意図的に起こすことができる。
  • retry を使って、begin の下に記述した処理を 再度やり直すことができる。
  • メソッド全体に例外処理を設ける場合は、beginend を省略することもできる。