How can I capture STDOUT to a string?
Solution 1
Redirect Standard Output to a StringIO Object
You can certainly redirect standard output to a variable. For example:
# 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
In practice, this is probably not a great idea, but at least now you know it's possible.
Solution 2
A handy function for capturing stdout into a string...
The following method is a handy general purpose tool to capture stdout and return it as a string. (I use this frequently in unit tests where I want to verify something printed to stdout.) Note especially the use of the ensure
clause to restore $stdout (and avoid astonishment):
def with_captured_stdout
original_stdout = $stdout # capture previous value of $stdout
$stdout = StringIO.new # assign a string buffer to $stdout
yield # perform the body of the user code
$stdout.string # return the contents of the string buffer
ensure
$stdout = original_stdout # restore $stdout to its previous value
end
So, for example:
>> str = with_captured_stdout { puts "hi"; puts "bye"}
=> "hi\nbye\n"
>> print str
hi
bye
=> nil
Solution 3
If activesupport is available in your project you may do the following:
output = capture(:stdout) do
run_arbitrary_code
end
More info about Kernel.capture
can be found here
Solution 4
You can do this by making a call to your R script inside backticks, like this:
result = `./run-your-script`
puts result # will contain STDOUT from run-your-script
For more information on running subprocesses in Ruby, check out this Stack Overflow question.
Solution 5
Minitest
versions:
assert_output
if you need to ensure if some output is generated:
assert_output "Registrars processed: 1\n" do
puts 'Registrars processed: 1'
end
or use capture_io
if you really need to capture it:
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
itself is available in any Ruby version starting from 1.9.3
Related videos on Youtube

Comments
-
script_kiddie almost 3 years
puts "hi" puts "bye"
I want to store the STDOUT of the code so far (in this case hi \nbye into a variable say 'result' and print it )
puts result
The reason I am doing this is I have integrate an R code into my Ruby code, output of which is given to the STDOUT as the R code runs , but the ouput cannot be accessed inside the code to do some evaluations. Sorry if this is confusing. So the "puts result" line should give me hi and bye.
-
SwiftMango almost 10 yearsIf you just want to get the stdout from external program, use result=%x{command}. Otherwise you can redirect stdio like showed by @codegnome
-
knut almost 10 yearsAre you using
rinruby
? I also tried to catch rinruby (R) output, but up to now without success. -
Ciro Santilli OurBigBook.com about 8 yearspossible duplicate of How do I temporarily redirect stderr in Ruby?
-
fearless_fool about 8 yearsIt's a nit, but stackoverflow.com/questions/4459330/… refers to
stderr
, this one tostdout
. You could merge them, but you'd want a search for "capture stdout" to find an answer as well as "capture stderr".
-
-
script_kiddie almost 10 yearsThis is exactly what i need .. but it does not work . can you just have a look at it again please ? its gives a blank output ..even the puts and hi abd byt insdei dont get printed . I have included require stringio .. THanks for the help ..
-
Todd A. Jacobs almost 10 yearsNo, they won't get printed, because you've redirected standard output to your StringIO. Use
STDOUT.puts $stdout.string
to print to the original output stream instead. -
script_kiddie almost 10 years.. this works but the other soln was what i was looking at .. thanks for the reply .. appreciate.
-
Jakub Jirutka almost 8 yearsActiveSupport’s Kernel#capture is deprecated and will be removed in some future release, because it’s not thread safe. See code and discussion.
-
prashant about 7 yearsNote that this won't necessarily work with, e.g.
Logger
, if it captures a reference to the original$stdout
before you have a chance to reassign it. -
Brian Underwood about 7 yearsExactly what I needed, thanks! FYI on a cool Ruby trick, if your
begin
/end
match the duration of your method, you can just skip them and just put theensure
at the end of your method (generally theensure
/rescue
is indented at the same level as the method'sdef
andend
) -
fearless_fool about 7 years@BrianUnderwood: True, but just because you can do something in Ruby doesn't always mean you should :). I included the
begin/end
statements mostly to make it easier for newcomers to understand. Old pros like you will know they can elide the begin/end in this case. -
Brian Underwood about 7 yearsI agree that there are some things you shouldn't do, but if this is a better syntax I would use it, even for beginners, because I don't think it's likely to confuse (and I love giving people an "I didn't know you could do that" moment even if that wasn't the point of the code). They say the best way to teach kids complicated words is to not shy away from them
-
Jeff about 5 yearsDoes this work with external commands? e.g. should this work?
with_captured_std_out { %x(wget http://google.com) }
I cant get it to work in this context. -
fearless_fool about 5 yearsIf
%x
is like backticks, it returns a string -- it doesn't print to stdout -- so you neither need nor want to wrap itwith_captured_std_out
. -
Artur INTECH over 4 yearsBrilliant! One remark: I would use
original_stdout
, instead ofold_stdout
-
Joshua Pinter almost 3 yearsHonestly, this was the only thing that worked for my cases where I wanted to call
Rake::Task[ "mytask" ].invoke
without outputting the result toSTDOUT
and instead capture it for later use. I restoreSTDOUT
immediately after using anensure
to avoid any issue. This might be dangerous if misused but it works very well when used sparingly. -
Dorian about 1 yearthis is a remote code execution vulnerability