将全局$ stdout重新分配给console - ruby

时间:2012-02-13 01:54:49

标签: ruby stdout iostream

我正在尝试将$ stdout设置为临时写入文件,然后返回文件。

test.rb :
   old_stdout = $stdout    
    $stdout.reopen("mytestfile.out",'w+')
       puts "this goes in mytestfile"
    $stdout= old_stdout
puts "this should be on the console"
    $stdout.reopen("mytestfile1.out",'w+')
       puts "this goes in mytestfile1:"
    $stdout = old_stdout
 puts "this should be back on the console"

这是输出。

ruby test.rb => no output on the console
cat mytestfile.out 
  this goes in mytestfile
  this should be on the console
cat  mytestfile1.out
  this goes in mytestfile1:
  this should be back on the console

我不确定为什么$ stdout没有重置为控制台?

2 个答案:

答案 0 :(得分:7)

在更改$stdout之前调用old_stdout = $stdout.dup $stdout.reopen("mytestfile.out",'w+') puts "this goes in mytestfile" $stdout = old_stdout.dup puts "this should be on the console" $stdout.reopen("mytestfile1.out",'w+') puts "this goes in mytestfile1:" $stdout = old_stdout puts "this should be back on the console" 可以解决此问题:

ruby test.rb
# => this should be on the console
# => this should be back on the console
cat mytestfile.out
# => this goes in mytestfile
cat mytestfile1.out
# => this goes in mytestfile1

输出:

# Runs a block of code while blocking stdout.
# Note that /dev/null should be changed to NUL on Windows.
def silence_stdout(log = '/dev/null')
  old = $stdout.dup
  $stdout.reopen(File.new(log, 'w'))
  yield
  $stdout = old
end

以下是我通常将此功能打包到函数中的方法:

silence_stdout 'mytestfile.out' do
  puts "this goes in mytestfile"
end

puts "this should be on the console"

silence_stdout 'mytestfile1.out' do
  puts "this goes in mytestfile1"
end

puts "this should be back on the console"

用法:

{{1}}

编辑:正如另一张海报所提到的,只有在使用纯Ruby代码时才需要使用reopen。上面的函数既可以使用纯Ruby代码,也可以使用例如写入STDOUT的C扩展。

答案 1 :(得分:3)

如果您只是使用Ruby代码,则无需使用reopenputs和其他Ruby方法将使用$stdout的当前值,因此您可以重新分配它。

old_stdout = $stdout    
$stdout = File.new("mytestfile.out",'w+')
puts "this goes in mytestfile"
$stdout = old_stdout
puts "this should be on the console"
$stdout = File.new("mytestfile1.out",'w+')
puts "this goes in mytestfile1:"
$stdout = old_stdout
puts "this should be back on the console"

如果您正在执行类似创建子进程的操作(例如使用reopen)并希望子输出转到别处,或者您有一个直接写入的扩展名,则只需要使用fork标准输出而不使用Ruby的$stdout全局。

在您的代码中,当您致电reopen时,您正在重定向 {/ 1>}和$stdout,因为它们都只是对同一IO对象的引用,这就是为什么在将old_stdout分配回old_stdout时,您无法将输出恢复到控制台。