2

In a Jupyter cell, I'd like to call a function that has some println, @show, etc in it, but I don't want to see those outputs. Is there a way to call a function while suppressing outputs? I'm aware of ;, but my understanding is that ; only affects the return value.

For example, let's say you have a function

function testOutputs()
    @show("Show macro still showing")
    println("Println still showing")
    a = 1 + 2
end

Calling testOutputs(); in a cell results in:

"Show macro still showing" = "Show macro still showing"
Println still showing

I would like it to print nothing.

GLee
  • 5,003
  • 5
  • 35
  • 39

2 Answers2

2

As phyatt's answer highlights it would often be better for library code to use a configurable logging mechanism. However, sometimes you want to call code that, for whatever reason, writes directly to stdout. One way to handle these cases is to use redirect_stdout.

For example:

real_stdout = stdout
(rd, wr) = redirect_stdout();
# Noisy code here
redirect_stdout(real_stdout)

You'd probably want to put this in a function or a macro or simply use Suppressor.jl a library that provides these macros. If you want to capture the output the way the ipython %%capture magic does you can have a look at @capture_out in Suppressor.jl, this SO question and this forum thread.

ahnlabb
  • 2,017
  • 1
  • 6
  • 16
  • Awesome, thanks! This is exactly what I was looking for. Agreed with both answers that configurable logging is better, but this covers more cases. – GLee Feb 26 '21 at 06:12
1

No one is stopping you from making those functions useless. It warns you that you must import from Base to actually override them.

julia> import Base.println

julia> println(args...) = nothing
println (generic function with 3 methods)

julia> import Base.@show

julia> macro show(args...)
       return :(nothing) # TODO: make this a pass thru instead of a removal
       end
@show (macro with 1 method)

julia> testOutputs()
3

julia> testOutputs();

Occasionally a programmer will put an @show in the middle of an expressions, and this kind of macro override would make it break such lines.

The better alternatives IMHO are to use a logging library like Memento.jl or the baked in Logging of julia. They have single line functions for mass disabling logging thru their mechanisms.

https://docs.julialang.org/en/v1/stdlib/Logging/
https://docs.julialang.org/en/v1/stdlib/Logging/#Logging.disable_logging

julia> @debug "Hello World"

julia> @info "Hello World"
[ Info: Hello World

julia> @warn "Hello World"
┌ Warning: Hello World
└ @ Main REPL[10]:1

julia> @error "Hello World"
┌ Error: Hello World
└ @ Main REPL[11]:1

julia> using Logging

julia> Logging.disable_logging(Logging.Error)
LogLevel(2001)

julia> @debug "Hello World"

julia> @info "Hello World"

julia> @warn "Hello World"

julia> @error "Hello World"

https://invenia.github.io/Memento.jl/latest/

Memento.config!("emergency")

Or without any additional libraries make a global flag at the top of your file called debug_print and swap it when needed.

julia> global debug_print = true
true

julia> function testOutputs()
           debug_print && @show("Show macro still showing")
           debug_print && println("Println still showing")
           a = 1 + 2
       end
testOutputs (generic function with 1 method)

julia> testOutputs();
"Show macro still showing" = "Show macro still showing"
Println still showing

julia> debug_print = false
false

julia> testOutputs();
phyatt
  • 18,472
  • 5
  • 61
  • 80