The documentation for redirect_stdout
on version 1.1.0, that I am currently using, does not seem to give an example of how to use that function. Maybe I missed it?
I want to capture the output of println
and get it back as a string.
Here is an example:
julia> VERSION
v"1.1.0"
julia> (rd, wr) = redirect_stdout();
julia> println("This is a test.")
julia> # Get back the string "This is a test."
julia> # s = do_something_with_rd(rd)
julia> # s == "This is a test."
julia> # true
Any suggestions?
Edit
Based on the accepted answer below, here is a complete solution to my question:
julia> original_stdout = stdout;
julia> (rd, wr) = redirect_stdout();
julia> println("This is a test.")
julia> s = readline(rd)
"This is a test."
julia> s == "This is a test."
true
julia> redirect_stdout(original_stdout);
julia> println("Test of orig. stdout.")
Test of orig. stdout.
Edit 2: A More Complete Example
Here is an example of testing a variety of print
and println
function outputs using redirection of stdout
. Thanks to @Bogumił Kamiński for his answer and edit that made this more clear to me:
using Test
# Test redirect_stdout.
@testset "Example tests using redirect_stdout" begin
original_stdout = stdout;
(read_pipe, write_pipe) = redirect_stdout();
print("Using print function.")
println("Using println function.")
println("Second use of println function.")
println("Line 1.\nLine 2.\nLine 3.\nEND")
println("""
This is new line 1.
This is new line 2. Next a Char = """)
print('A')
redirect_stdout(original_stdout);
close(write_pipe)
@test readline(read_pipe) == "Using print function.Using println function."
@test readline(read_pipe) == "Second use of println function."
@test read(read_pipe, String) == "Line 1.\nLine 2.\nLine 3.\nEND\n" *
"This is new line 1.\nThis is new line 2. Next a Char = \nA"
end
# Suppress unnecessary output when this file.
return nothing
Here is the output:
julia> include("test_redirect_stdout.jl")
Test Summary: | Pass Total
Example tests using redirect_stdout | 3 3
Just run readline
on rd
(or any other reading operation).
You have just to be careful that read operations on rd
are blocking, i.e. the terminal will seem to hang when the operation cannot be completed. One solution is to use @async
for this. For instance:
julia> (rd, wr) = redirect_stdout();
julia> @async global x = readline(rd) # if we did not put @async here the terminal would be blocked
Task (runnable) @0x0000000004e46e10
julia> x # x is yet undefined as readline is waiting for an input
ERROR: UndefVarError: x not defined
julia> println("something") # we feed data to stdout
julia> x # and readline has finished its work and bound the value to variable x
"something"
Of course if you know exactly that the data you want to read in is there just run readline
or some other function and all will work without @async
.
EDIT
Given the comments from SalchiPapa I think it is also add this pattern of possible usage as it is simplest to think of IMO:
original_stdout = stdout
(rd, wr) = redirect_stdout();
println("This is a test 1.")
println("This is a test 2.")
println("This is a test 3.")
redirect_stdout(original_stdout)
# you can still write to wr
println(wr, "This is a test 4.")
# you have to close it to make the read non-blocking
close(wr)
# the pipe is redirected to original stdout and wr is closed so this is non-blocking
s = read(rd, String)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With