puts "hi"
puts "bye"
Je veux stocker le STDOUT du code jusqu'à présent (dans ce cas, salut\nbye dans une variable, dites "résultat" et imprimez-le)
puts result
La raison pour cela est que j’ai intégré un code R dans mon code Ruby, dont la sortie est transmise à STDOUT pendant l’exécution du code R, mais il n’est pas possible d’accéder à la sortie dans le code pour effectuer certaines évaluations. Désolé si c'est déroutant. Donc, la ligne "met le résultat" devrait me donner salut et au revoir.
Vous pouvez certainement rediriger la sortie standard vers une variable. Par exemple:
# Set up standard output as a StringIO object.
foo = StringIO.new
$stdout = foo
# Send some text to $stdout.
puts 'hi'
puts 'bye'
# Access the data written to standard output.
$stdout.string
# => "hi\nbye\n"
# Send your captured output to the original output stream.
STDOUT.puts $stdout.string
En pratique, ce n'est probablement pas une bonne idée, mais au moins maintenant, vous savez que c'est possible.
La méthode suivante est un outil pratique très utile pour capturer stdout et le renvoyer sous forme de chaîne. (J'utilise cela fréquemment dans les tests unitaires où je veux vérifier quelque chose imprimé sur stdout.) Notez en particulier l'utilisation de la clause ensure
pour restaurer $ stdout (et éviter les surprises):
def with_captured_stdout
original_stdout = $stdout
$stdout = StringIO.new
yield
$stdout.string
ensure
$stdout = original_stdout
end
Donc, par exemple:
>> str = with_captured_stdout { puts "hi"; puts "bye"}
=> "hi\nbye\n"
>> print str
hi
bye
=> nil
Si ActiveSupport est disponible dans votre projet, vous pouvez procéder comme suit:
output = capture(:stdout) do
run_arbitrary_code
end
Plus d'informations sur Kernel.capture
peuvent être trouvées ici
Vous pouvez le faire en appelant votre script R à l'intérieur de butées, comme ceci:
result = `./run-your-script`
puts result # will contain STDOUT from run-your-script
Pour plus d'informations sur l'exécution de sous-processus dans Ruby, consultez cette question de débordement de pile .
Dans la plupart des cas, vous pouvez insérer n'importe quoi dans $stdout
qui répond à write
, flush
, sync
, sync=
et tty?
.
Dans cet exemple, j'utilise un Queue modifié à partir de stdlib.
class Captor < Queue
alias_method :write, :Push
def method_missing(meth, *args)
false
end
def respond_to_missing?(*args)
true
end
end
stream = Captor.new
orig_stdout = $stdout
$stdout = stream
puts_thread = Thread.new do
loop do
puts Time.now
sleep 0.5
end
end
5.times do
STDOUT.print ">> #{stream.shift}"
end
puts_thread.kill
$stdout = orig_stdout
Vous avez besoin de quelque chose comme ceci si vous voulez agir activement sur les données et ne pas simplement les regarder une fois la tâche terminée. Utiliser StringIO ou un fichier sera problématique avec plusieurs threads essayant de synchroniser les lectures et les écritures simultanément.
Minitest
versions:
assert_output
si besoin de s’assurer que des sorties sont générées:
assert_output "Registrars processed: 1\n" do
puts 'Registrars processed: 1'
end
ou utilisez capture_io
si vous avez vraiment besoin de le capturer:
out, err = capture_io do
puts "Some info"
warn "You did a bad thing"
end
assert_match %r%info%, out
assert_match %r%bad%, err
Minitest
lui-même est disponible dans toutes les versions de Ruby à partir de 1.9.3
Pour RinRuby, sachez que R a capture.output
:
R.eval <<EOF
captured <- capture.output( ... )
EOF
puts R.captured