Ruby Users' Guide - 例外処理

前 - コピー - 次 - 目次

### 例外処理

プログラムの動作に例外的な状況はつきものだ．ファイルをオープ ンしようとすれば，ファイルが存在しないかも知れないし，書き込 もうとすれば，ディスクがいっぱいかも知れない．こういう状況を 考慮していないプログラムは品質が悪いといわれる．

問題は例外的な状況が発生したかどうかが，いちいち「今の処理は 大丈夫でしたか」と確認しなければ分からないことだ．例外的な状 況で処理が正しく行われていないのに続きを実行すれば，当然問題 が起きる．例外的な状況が発生したら，そのまま処理を続けてはい けないのだ．

rubyではこういう例外的な状況では「例外」が発生する．特になに も対処しなければ，「例外」はプログラムの実行を中断する．これ で例外的な状況に対処せずに処理を続けてしまう心配は無い．

     ruby> file =open("/file_not_exist")
     ERR: No such file or directory - /file_not_exist

Cなどならオープンできたかプログラマがチェックする必要がある が．rubyでは「例外が発生していないのでちゃんと処理が行われた」 と仮定することができる．Cで書くとこういう風になる．

    FILE *file = fopen("/file_not_exist", "r");
    if (file == NULL) { /* エラー処理 */ }

エラー処理する必要がない分，プログラムがすっきりするのが分か るだろう．

先程も説明したように，例外が発生すると，プログラムの実行は中 断される．が，それでは嬉しくないことも多いだろう．例外の原因 に対応してプログラムを継続したい場合もあるはずだ．そういう時 には'begin'を使って，例外を捕捉する必要がある．使い方はこう だ．

     ruby> begin
     ruby|   file = open("/file_not_exists")
     ruby| rescue
     ruby|   file = STDIN
     ruby| end
     #<IO:0x93490>
     ruby> print file, "==", STDIN, "\n"
     #<IO:0x93490> == #<IO:0x93490>
     nil

openに失敗したので，fileにSTDINが代入されたのが分かるだろう．

beginは本体を実行している最中に例外が起きるとrescue以下のエ ラー処理を実行する．

beginには「やり直し」の機能もある．これには`retry'を使う． rescueの中でretryが使われるとbeginのはじめから実行をやり直す． これを応用するとこんな感じになる．

     ruby> fname = "file_not_exists"
     ruby> begin
     ruby|   file = open(fname)
     ruby|   # なにか file を使った処理
     ruby| rescue
     ruby|   fname = "file_exists"
     ruby|   retry
     ruby| end
     #<File:0x68890>

fileのオープンに失敗するとfnameに代わりのファイル名を代入し てやり直すわけだ．処理の流れは以下のようになる．

- openで例外が発生する
- rescue以下へ，fnameに再代入する
- retryでbeginの最初に
- 今度はopenで成功する
- 本来の処理

しかし，例えば再代入した名前のファイルも存在しなければ，この 例では無限ループに陥ってしまう．retryを使う時には，例外処理 に気を使った方が良い．

rubyのライブラリはエラーが起きた時に例外を発生させるようになっ ているが，もちろん自分で例外を発生させることができる．例外を 発生させるには`raise'を使う．raiseには例外の状況を説明する文 字列を引数に与える．この文字列は説明する必要がない時には省略 できる(が省略しない方が良い)．この文字列は後から変数`$!'で参 照できる．

     ruby> raise "test error"
     ERR: test error
     ruby> begin
     ruby|   raise "test2"
     ruby| rescue
     ruby|   print $!, "\n"
     ruby| end
     test2
     nil

前 - コピー - 次 - 目次