Redirect stdout and stderr?

question
#1

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?

1 Like

#2

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.

0 Likes

#3

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.

2 Likes

#4

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?

1 Like

#5

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
1 Like