J'aimerais temporairement rediriger stderr dans un script Ruby pour la durée d'un bloc, veillant à ce que je le réinitialiser à sa valeur d'origine à la fin du bloc.
J'ai eu du mal à trouver comment faire cela dans le rubis docs.
J'aimerais temporairement rediriger stderr dans un script Ruby pour la durée d'un bloc, veillant à ce que je le réinitialiser à sa valeur d'origine à la fin du bloc.
J'ai eu du mal à trouver comment faire cela dans le rubis docs.
En Ruby, $stderr
désigne le flux de sortie qui est actuellement utilisé comme stderr, alors qu' STDERR
est la valeur par défaut flux stderr. Il est facile d'attribuer temporairement un autre flux de sortie d' $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
Maintenant, vous pouvez effectuer les opérations suivantes:
captured_output = capture_stderr do
# Does not output anything directly.
$stderr.puts "test"
end
captured_output
#=> "test\n"
Le même principe fonctionne aussi pour d' $stdout
et STDOUT
.
Ici est un résumé de la solution (crédit va à David 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
Utilisation:
silence_streams(STDERR) { do_something }
Essentiellement la même chose que @molf réponse, et a le même usage:
require "stringio"
def capture_stderr
real_stderr, $stderr = $stderr, StringIO.new
yield
$stderr.string
ensure
$stderr = real_stderr
end
Il utilise StringIO très légèrement de façon plus concise, et préserve $stderr comme ce qu'il était avant capture_stderr a été appelé.
J'aime la StringIO réponses. Mais si vous appelez d'un processus externe, et $stderr = StringIO.new
ne fonctionne pas, vous pouvez écrire stderr dans un fichier temporaire:
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
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.