Hide output from external function

I am using a package, Chemfiles, which has a function to read some simulation trajectory files. This function is a wrapper to a C++ function, and this C++ function writes to “the screen” (?) some stuff every time a file is read:

julia> using Chemfiles

julia> Chemfiles.Trajectory("./o1.dcd")
dcdplugin) detected standard 32-bit DCD file of native endianness
dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)
dcdplugin) detected standard 32-bit DCD file of native endianness
dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)
Trajectory(Chemfiles.CxxPointer{Chemfiles.lib.CHFL_TRAJECTORY}(Ptr{Chemfiles.lib.CHFL_TRAJECTORY} @0x000000000162c190, false), nothing)

The last line is the return value. But the other lines dcdplugin)… are only polluting the repl. Is there a way to suppress/capture that printing such that it does not show up?

something like this maybe:
https://docs.julialang.org/en/v1/base/io-network/#Base.redirect_stdout-Tuple{Function,%20Any}

1 Like

Seems that that might do it, but I don’t understand how to use it. How should I do to redirect the output to a devnull, for example, or to anywhere else? My understanding of the IO stuff is null.

julia> t = redirect_stdout(Chemfiles.Trajectory("./o1.dcd"),devnull)
dcdplugin) detected standard 32-bit DCD file of native endianness
dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)
dcdplugin) detected standard 32-bit DCD file of native endianness
dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)
ERROR: MethodError: no method matching redirect_stdout(::Trajectory, ::Base.DevNull)
Closest candidates are:
  redirect_stdout(::Function, ::Any) at stream.jl:1219
Stacktrace:
 [1] top-level scope
   @ REPL[16]:1

julia> t = redirect_stdout(Chemfiles.Trajectory("./o1.dcd"),Pipe())
dcdplugin) detected standard 32-bit DCD file of native endianness
dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)
dcdplugin) detected standard 32-bit DCD file of native endianness
dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)
ERROR: MethodError: no method matching redirect_stdout(::Trajectory, ::Pipe)
Closest candidates are:
  redirect_stdout(::Function, ::Any) at stream.jl:1219
Stacktrace:
 [1] top-level scope
   @ REPL[17]:1


the first argument has to be a callable, function:

julia> f() = begin println(stdout, "a"); return 2 end
f (generic function with 1 method)

julia> f()
a
2

julia> b = redirect_stdout(f, devnull);

julia> b
2
1 Like

Nice, seems to work:

julia> t = redirect_stdout(() -> Chemfiles.Trajectory("./o1.dcd"),devnull)
Trajectory(Chemfiles.CxxPointer{Chemfiles.lib.CHFL_TRAJECTORY}(Ptr{Chemfiles.lib.CHFL_TRAJECTORY} @0x00000000012fdb00, false), nothing)


1 Like

Something curious: the solution above works. However, I am running that within a @testset block. The messages are not printed during the tests, but they are shown after all tests are finished. Any idea?

Test Summary: | Pass  Total
NAMD          |    8      8
dcdplugin) detected standard 32-bit DCD file of native endianness
dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)
dcdplugin) detected standard 32-bit DCD file of native endianness
dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)
dcdplugin) detected standard 32-bit DCD file of native endianness
dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)
dcdplugin) detected standard 32-bit DCD file of native endianness
dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)
dcdplugin) detected standard 32-bit DCD file of native endianness
dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)
dcdplugin) detected standard 32-bit DCD file of native endianness
dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)
dcdplugin) detected standard 32-bit DCD file of native endianness
dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)
dcdplugin) detected standard 32-bit DCD file of native endianness
dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)
dcdplugin) detected standard 32-bit DCD file of native endianness
dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)
dcdplugin) detected standard 32-bit DCD file of native endianness
dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)
dcdplugin) detected standard 32-bit DCD file of native endianness
dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)
dcdplugin) detected standard 32-bit DCD file of native endianness
dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)
dcdplugin) detected standard 32-bit DCD file of native endianness
dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)
dcdplugin) detected standard 32-bit DCD file of native endianness
dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)
dcdplugin) detected standard 32-bit DCD file of native endianness
dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)
dcdplugin) detected standard 32-bit DCD file of native endianness
dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)
     Testing CellListMap tests passed 

no idea, probably because it’s already been taken before stdout so redirect_stdout did nothing

1 Like

It did something, because without it the garbage is print before the result:

dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)
dcdplugin) detected standard 32-bit DCD file of native endianness
dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)
dcdplugin) detected standard 32-bit DCD file of native endianness
dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)
Test Summary: | Pass  Total
NAMD          |    8      8
     Testing CellListMap tests passed 

Ah, look at that: if I do that in a MWE, what happens is that the garbage is print when I quit Julia:

julia> using Chemfiles

julia> function getcoor(file)
           traj = redirect_stdout(()->Chemfiles.Trajectory(file),devnull)
           return true
       end
getcoor (generic function with 1 method)

julia> using Test

julia> @testset "NAMD" begin
          @test getcoor("o1.dcd")
       end
Test Summary: | Pass  Total
NAMD          |    1      1
Test.DefaultTestSet("NAMD", Any[], 1, false, false)

julia> # Control-D
dcdplugin) detected standard 32-bit DCD file of native endianness
dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)
dcdplugin) detected standard 32-bit DCD file of native endianness
dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)
namd% 

A bit more context here: these messages come from the VMD DCD plugin, used by chemfiles to read DCD files, see here for example. All VMD plugins uses “prints to stderr/stdout” as a very basic form of logging, which I agree is quite annoying :smiley:

My best guess is that the test framwork is already redirecting stdout, and collecting the full output to show it after all tests ran. This part of the stdlib looks partially related

1 Like