将全局$ stdout重新分配给console – ruby
我试图设置$ 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没有重置为控制台?
在更改它之前调用$stdout
上的dup可以解决此问题:
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
以下是我通常将此function打包到函数中的方法:
# 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"
编辑:正如另一张海报所提到的,只有在使用纯Ruby代码时才需要使用reopen。 上面的函数既适用于纯Ruby代码,也适用于使用例如写入STDOUT的C扩展。
如果您只使用Ruby代码,则无需使用reopen
。 puts
和其他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"
如果您正在执行诸如创建子进程(例如使用fork
)并希望子进程转到别处,或者如果您有一个直接写入标准输出而不使用Ruby的$stdout
全局$stdout
的扩展,则只需要reopen
。
在您的代码中,当您调用reopen
您将重定向$stdout
和old_stdout
,因为它们都只是对同一IO对象的引用,这就是为什么在将old_stdout
分配回stdout
时不会将输出返回到控制台的old_stdout
。