-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Description
The usability of the redirect_stdout etc. functions got a big boost with the do versions, but there are still some gotchas that make them often inconvenient, and I think they can be improved without any breaking changes:
Sometimes you just want to throw away output
This could be written as:
redirect_stdout(devnull) do
# noisy code here
endThis was proposed in #22879, and seems like it would need a cross-platform way to open a null file. It looks like on windows you can open("nul", "w"). So this could be implemented as something like:
function Base.redirect_stdout(dofunc::Function, ::Base.DevNullStream)
nullfile = @static Sys.iswindows() ? "nul" : "/dev/null"
open(nullfile, "w") do io
redirect_stdout(dofunc, io)
end
endIt's come up before that the redirect_ functions don't support more generic IO types
This was mentioned in the above issue, and also in #12711. It would look like:
io = IOBuffer()
redirect_stdout(io) do
# code
end
seekstart(io)
read(io) # get the infoCapturing to a string is a multi-step process
It's common in testing to check that your code is outputting what you expect, so an easy way to capture to a string would be useful. This could be:
output = redirect_stdout() do
# test code here
endThis implementation for both these last two could look very similar to the @capture_out macro from Suppressor.jl except that there's no need for it to be a macro (originally those were macros so that the macro didn't affect the expression's scope, but that got blown out of the water when we added the try...finally block).:
function Base.redirect_stdout(dofunc::Function, io::Union{IO,Nothing}=nothing)
if ccall(:jl_generating_output, Cint, ()) == 0
original_stdout = stdout
out_rd, out_wr = redirect_stdout()
out_reader = @async if io === nothing
read(out_rd, String)
else
read(out_rd)
end
end
out = io === nothing ? "" : UInt8[]
try
dofunc()
finally
if ccall(:jl_generating_output, Cint, ()) == 0
redirect_stdout(original_stdout)
close(out_wr)
out = fetch(out_reader)
end
end
if io === nothing
out
else
write(io, out)
nothing
end
endTBH I'm not 100% sure what the if ccall(:jl_generating_output, Cint, ()) == 0 checks are for, I think they came from some of @keno's code
These methods are all currently errors, so it seems like they could be candidates for a 1.x release if they seem like OK ideas.