💎
Ruby 3.2 - OptionParser / Timeout
Ruby 3.2 アドベントカレンダーの23日目の記事です。
default gem のバージョンアップで面白いのがあるかなーと眺めてみた。
OptionParser
OptionParser#raise_unknown
Mode for accepting all unknown options · Issue #38 · ruby/optparse
raise_unknown
に偽を指定すると未知のオプションが指定されてもエラーにならないらしい。
--hoge
オプションが有効なプログラムを作って、
require 'optparse'
opts = OptionParser.new do |opts|
opts.on('--hoge'){puts 'hoge option'}
end
opts.parse!(ARGV)
これに --fuga
を与えると落ちる。
% ruby hoge.rb --hoge --fuga abc
hoge option
hoge.rb:7:in `<main>': invalid option: --fuga (OptionParser::InvalidOption)
raise_unknown
に偽を指定すると落ちない。それはオプションではない普通の引数として扱われるぽい。
require 'optparse'
opts = OptionParser.new do |opts|
opts.on('--hoge'){puts 'hoge option'}
end
opts.raise_unknown = false
opts.parse!(ARGV)
pp ARGV
% ruby hoge.rb --hoge --fuga abc
hoge option
["--fuga", "abc"]
ただし、普通は通常の引数の後ろにオプションがあってもオプションとして解釈されるんだけど、
% ruby hoge.rb abc --hoge
hoge option
["abc"]
未知のオプションがあった場合はそれ以降に正しいオプションがあってもオプションとはみなされないぽい。
% ruby hoge.rb --fuga --hoge abc
["--fuga", "--hoge", "abc"]
そこで引数の評価を打ち切るって感じなのかな。
Timeout
Timeout.timeout が一つのスレッドで動く
以前は Timeout.timeout
は実行されるたびにスレッドがひとつ生成されたので、わりと負荷が高い処理だった。
timeout gem 0.3.1 では、ひとつのスレッドを使いまわすようになったらしい。
こんなスクリプトを実行してみると、
require 'timeout'
def hoge(c)
if c > 0
Timeout.timeout(10){hoge(c-1)}
else
system("ps -o nlwp -p #$$")
end
end
hoge(100)
Ruby 3.1 (timeout gem 0.2.0):
% ruby timeout-test.rb
NLWP
101
Ruby 3.2 (timeout gem 0.3.1):
% ruby timeout-test.rb
NLWP
2
timeout gem 0.3.1 ではスレッドを消費してないことがわかる。
Discussion