Disable IOStream buffering or replace by unbuffered IO

I have a script written in Julia. It is written in Julia and not bash because: (1) the script will call Julia anyway, and I want to warm-start the JIT to avoid measuring compile time and to reduce the total time used by the script; (2) because writing a complex script in bash is painful.

One of the things the script should do is to redirect the default and error output to files. For this I am using:

function save_output_in_path(f, path :: AbstractString)
  open(path, "a+") do file
    redirect_stdout(() -> redirect_stderr(f, file), file) 
  end 
end

However, this changes the “normal” behavior of the code. As the output is now buffered and I need to call a flush(file) or flush(stdin); flush(stdout) (this last seems to be the real alternative to me, as the file is not available in many scopes I want the output to be flushed). The problem is aggravated by the fact: (1) I want an immediate flush to be able to better debug the code, as any relevant messages will have been printed before the error is raised (and errors may happen anywhere); (2) most importantly, I call the Gurobi solver in my code, and while its output is correctly redirected (the fact this works seamlessly made me really happy) it is not buffered like the rest, so if I do not flush before calling it, my debug output will only appear after the output of the solver, what really makes hard to me to not get confused while reading the output (there are inner loops in the module used by the script that output some info and call optimize, repeated times, so all solver outputs appear before all of these debug prints).

Seems to me that replacing the file by an unbuffered version of IOStream (that is the type of the object returned by open) would solve the problem, but I had no success trying to do so. I have not found a way to disable the buffering in IOStream objects, and trying to use a wrapper approach like here did not work (as many methods seem to expect to know the fields of the passed object).

2 Likes

So, there is no way to do it? I would have expected to have been missing on something obvious.

For now I have just placed flush(stdin); flush(stdout) in many places of my code (to avoid having to globalize file or pass it around).

1 Like