みんなのちからになりたい

コピペでブログラムつくっていきたい

rubyで標準エラーに出力するのはいいけどどうやって読むのか

たぶんそうとうアホなこと書いてると思うんだけど、例えばファイルを読むとき例外が出たらSTDERR.putsとかでエラーを書いたりするみたいなんだけど、普通はコンソールに出力されるだけでそれを呼んだメソッドとかはどうやって読むつもりでいるのかという疑問が起きた。
業務アプリとか書いてるとメソッドとかでエラーが出る場合は戻り値はboolでクラスにエラーメッセージを格納するメンバとか作ってそれを読むみたいなのがありがちだと思うんだけど、rubyに限らずjavascriptとかperlとかのgithubにあるいろんなsource読むと例外処理を入れてない漢らしいメソッドがけっこうあって、例外が起きたときはなるがままに落として呼んだほうで例外を拾って対処するのが一般的なのかもしれない。
こういうのは仕様とか実装の問題だと思うんだけど、どこまでクラスが責任を持つべきなのかというのがわけわからなくなってきてる。

それはともかく、いくら例外をrescueで拾ってSTDERRに書いたところでそれを読めないのならなにが理由でダメだったのか知る手段がないんじゃないかと思ったので読んでみたい。

リファレンス読むとSTDERRは$stderrのデフォルト値で要はIOクラスっぽい。

variable $stderr

これ読むとそのものズバリでSTDERRの出力先を変えることができて、それを読めばいいということになる。
reopenの引数はIOなのでファイルでもいいんだけど、IOのリファレンスをずーっと読んでいくとpipeってやつがreadとwriteのIOを返してくれるっぽい。
これは相互につながってるらしいので、片方で書いたら片方で読めるということになる(と思う)
試してみる。

STDERR.puts "start"
stderr = STDERR.dup
r, w = IO.pipe
STDERR.reopen w
STDERR.puts "puts"
p r.readline
STDERR = stderr


$ruby std.rb
start
"puts\n"

ちゃんと読める。すごい。
念のため、readlineをコメントにしてみる。

STDERR.puts "start"
stderr = STDERR.dup
r, w = IO.pipe
STDERR.reopen w
STDERR.puts "puts"
#p r.readline
STDERR = stderr


$ruby std.rb
start

出ない。すごい。

ということは、STDINにpipeのreadをセットすればSTDIN.readlineで読めるのではないか。
やってみる。

STDERR.puts "start"
stderr = STDERR.dup
stdin = STDIN.dup
r, w = IO.pipe
STDERR.reopen w
STDIN.reopen r
STDERR.puts "puts"
p STDIN.readline
STDERR.reopen stderr
STDIN.reopen stdin

$ruby std.rb
start
"puts\n"

読める。すごい。

というかここまでやって思ったけど、なにもせずSTDERRとかSTDOUTに出力したら拾えないってことだとしたらいまやったことは目的を果たしていないというか無駄なことだったっていうか...
いろいろぐぐってるけどそれらしいものはまだみつかってないので、できるのかできないのかすらまだわかってない。
よくわからない。