如何在Ruby中暂时redirectstderr?
我希望在一个块的持续时间内暂时将stderrredirect到一个Ruby脚本中,以确保在块的末尾将其重置为原始值。
我很难find如何在ruby文档中做到这一点。
在Ruby中, $stderr
引用当前用作 stderr的输出stream,而STDERR
是默认的 stderrstream。 临时将不同的输出stream分配给$stderr
是很容易的。
require "stringio" def capture_stderr # The output stream must be an IO-like object. In this case we capture it in # an in-memory IO object so we can return the string value. You can assign any # IO object here. previous_stderr, $stderr = $stderr, StringIO.new yield $stderr.string ensure # Restore the previous value of stderr (typically equal to STDERR). $stderr = previous_stderr end
现在您可以执行以下操作:
captured_output = capture_stderr do # Does not output anything directly. $stderr.puts "test" end captured_output #=> "test\n"
同样的原理也适用于$stdout
和STDOUT
。
这是一个更抽象的解决scheme(信贷大卫Heinemeier Hansson):
def silence_streams(*streams) on_hold = streams.collect { |stream| stream.dup } streams.each do |stream| stream.reopen(RUBY_PLATFORM =~ /mswin/ ? 'NUL:' : '/dev/null') stream.sync = true end yield ensure streams.each_with_index do |stream, i| stream.reopen(on_hold[i]) end end
用法:
silence_streams(STDERR) { do_something }
基本上和@ molf的答案一样,并且具有相同的用法:
require "stringio" def capture_stderr real_stderr, $stderr = $stderr, StringIO.new yield $stderr.string ensure $stderr = real_stderr end
它使用StringIO非常简洁,保存了$ stderr,就像调用capture_stderr之前的那样。
我喜欢StringIO的答案。 但是,如果您调用外部进程,并且$stderr = StringIO.new
不起作用,则可以将stderr写入临时文件:
require 'tempfile' def capture_stderr backup_stderr = STDERR.dup begin Tempfile.open("captured_stderr") do |f| STDERR.reopen(f) yield f.rewind f.read end ensure STDERR.reopen backup_stderr end end