Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Julia 1.0+: How do I get strings using redirect_stdout

Tags:

julia

The documentation for redirect_stdouton 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
like image 857
Julia Learner Avatar asked Jan 01 '23 07:01

Julia Learner


1 Answers

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)
like image 163
Bogumił Kamiński Avatar answered Feb 19 '23 21:02

Bogumił Kamiński