A minimal example with Base.redirect_stdout

Hello all

I’m having a bit of difficulty making the Base.redirect_stdout(f::Function, stream) method work. What I would have thought would be a minimal working example is in fact a minimal failing example:

out = Pipe()
redirect_stdout(out) do s
    println("stick this in your pipe")
end

This gives me
ERROR: MethodError: no method matching redirect_stdout(::Pipe)

Who’s in the wrong here - me, or Julia? Any help much appreciated. It seems like a nifty function and it’s annoying not to be able to use it.

Link to the docs below:
https://docs.julialang.org/en/v1/base/io-network/#Base.redirect_stdout-Tuple{Function,%20Any}

Redirection to Pipe is not supported on Julia 1.6. You can redirect to a file stream:

julia> open("/tmp/stdout", "w") do io
           redirect_stdout(io) do
               println("hello, world")
           end
       end

julia> read("/tmp/stdout", String)
"hello, world\n"

In the upcoming Julia 1.7 Pipe is supported, though (JuliaLang/julia#39132).

Why though? The docs very clearly state that it is:
https://docs.julialang.org/en/v1/base/io-network/#Base.redirect_stdout-Tuple{Function,%20Any}

Bug in the documentation (JuliaLang/julia#31159).

OK. Seems like a handy function when it’s ready.

This works in Julia 1.7-beta2:

pipe = Pipe()
output = IOBuffer()
cmd = run(pipeline(pipe, `wc -l`, result), wait=false)
redirect_stdout(pipe) do
    print(pipe, "a\nb\n")
end

close(pipe)
wait(cmd)

julia> result = String(take!(output))
"2\n"

You can also read directly from the pipe, but don’t forget that pipe writes will block if the pipe is full (because the reader is slower), so you need something like this:

pipe = Pipe()
writer = @async redirect_stdout(pipe) do
    write(stdout, String(rand(['a':'z'; '\n'], 100_000)))
    close(Base.pipe_writer(pipe))
end

result = read(pipe, String)
wait(writer)  # Not really necessary but cleaner

It’s maybe a bit hacky to use the unexported pipe_writer function, and to close the stream before the end of redirect_stdout… This should all be made simpler, see the following issues: