遠藤です。

2009年10月3日15:48 Tanaka Akira <akr / fsij.org>:
> In article <e0b1e5700910022319w60926de8lc81e8881602a0fc / mail.gmail.com>,
>  Yusuke ENDOH <mame / tsg.ne.jp> writes:
>
>> open-uri を使って定期的に Web ページを取得するプログラムを走らせて
>> いると、実にさまざまな例外が投げられうることに気がつきました。
>
> 奇遇なことに、私も似たようなことをやっています。
> samidare というプログラムですが。

なるほど (笑)


>> 1) open-uri が投げうる例外は他にあるでしょうか (Errno::* はいくらでも
>> ありそうですが) 。
>
> 私がやっているもののログをいましらべたら、とりあえず、あげら
> れている以外に
>
> Errno::ECONNREFUSED
> Errno::ENETUNREACH
>
> が見つかりました。

うう、ありがとうございます。とりあえず手元でも対処しておきます。


>> 2) この中で本来投げられるべきでない例外はないでしょうか。EOFError は
>> 少し怪しいと思っています。バグだとしても Net::HTTP か Timeout のバグ
>> だと思いますが。ちなみに再現させる方法はもちろんわかりません。
>
> EOFError は以前なにかの飲み会で青木さんに文句を言った覚えが
> あります。

うーん、redmine に登録すべきか。


>> 3) この状況に対して、open-uri のユーザはどのように対処することが要求
>> されているのでしょうか。4 つ思いつきました。
>>
>>   A. StandardError を rescue してまとめて対処する
>
> 私がやっているものをみたら、これでした。

「open-uri を使うときは rescue StandardError でくるむ」という
イディオムが推奨されるわけですかね。

しかし open をブロック付きで使うことを考えると、それは少し不便です。

  open("http://...") do |fh|
    ... # (A)
  end

を

  begin
    open("http://...") do |fh|
      ... # (A)
    end
  rescue StandardError
    ... # (B)
  end

とした場合、(A) の中で発生した例外が全部 (B) に拾われてしまいます。
(A) の中にバグがあって例外が投げられた場合などは、(B) で拾わずに外に
投げて欲しいと思います。


そこで提案ですが、open-uri の内部で発生した例外は open-uri の中で
すべて拾って、OpenURI::Error などと言った名前の例外にくるんで投げ
なおすというのはどうでしょうか。
ユーザは OpenURI::Error だけを拾えばいいということになって、気楽
です。

-- 
Yusuke ENDOH <mame / tsg.ne.jp>