Эта проблема может быть решена путем вызова dup на $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"
Редактировать: как уже упоминалось, использование reopen необходимо только при работе с чистым кодом Ruby. Вышеприведенная функция работает как с чистым кодом Ruby, так и при использовании, например, расширений C, которые записывают в STDOUT.