Redirect stdout and stderr?

I want to do a computation with stdout and stderr both redirected to files. Here is what I wrote:

open(prefix * ".log", "w") do out
    open(prefix * ".err", "w") do err
        redirect_stdout(out) do
            redirect_stderr(err) do
                compute(...)
            end
        end
    end
end

Is there a better way to write this and reduce the nestedness?

You can open and close the streams manually, or you could wrap your business logic in a function f to pass to redirect_stderr(f, stream). That way only the redirection is nested.

Yeah, I think that’s a pretty reasonable way to write it, but if it’s something you’re doing a lot you could write a convenience wrapper:

function redirect_to_files(dofunc, outfile, errfile)
    open(outfile, "w") do out
        open(errfile, "w") do err
            redirect_stdout(out) do
                redirect_stderr(err) do
                    dofunc()
                end
            end
        end
    end
end

Which you would then use like:

redirect_to_files(prefix * ".log", prefix * ".err") do
    compute(...)
end

or even combine both filenames into a single prefix arg if you know they’re always going to be prefix.log and prefix.err.

Is this expected to work for functions that execute ccall?

It doesn’t seem to work in this case:

using Random, RNGTest

rng = RNGTest.wrap(MersenneTwister(), UInt64);
RNGTest.smallcrushTestU01(rng)   # successful output to terminal

open("test.txt", "w") do fileio
    redirect_stdout(fileio) do
        RNGTest.smallcrushTestU01(rng)   # executes `ccall`
    end
end

file “test.txt” is created but it is empty; no output to terminal.

Am I doing something wrong here, or is it not expected to work?

Can get it to work by flushing c stdout with Base.Libc.flush_cstdio()

open("test.txt", "w") do fileio
    redirect_stdout(fileio) do
        RNGTest.smallcrushTestU01(rng)   # executes `ccall`
        Base.Libc.flush_cstdio()
    end
end

Since Julia 1.7, there is redirect_stdio which does this, I/O and Network · The Julia Language