Is there a way in Python to silence stdout without wrapping a function call like following?
Original Broken Code:
from sys import stdout
from copy import copy
save_stdout = copy(stdout)
stdout = open('trash','w')
foo()
stdout = save_stdout
Edit: Corrected code from Alex Martelli
import sys
save_stdout = sys.stdout
sys.stdout = open('trash', 'w')
foo()
sys.stdout = save_stdout
That way works but appears to be terribly inefficient. There has to be a better way. Any ideas?
Just to add to what others already said, Python 3.4 introduced the
contextlib.redirect_stdout
context manager. It accepts a file(-like) object to which the output is to be redirected.Redirecting to /dev/null will suppress the output:
This solution can be adapted to be used as a decorator:
Another possible and occasionally useful solution that will work in both Python 2 and 3 is to pass /dev/null as an argument to
f
and redirect the output using thefile
argument of theprint
function:You can even make
target
completely optional:Note, you'll need to
in Python 2.
Assigning the
stdout
variable as you're doing has no effect whatsoever, assumingfoo
containsprint
statements -- yet another example of why you should never import stuff from inside a module (as you're doing here), but always a module as a whole (then use qualified names). Thecopy
is irrelevant, by the way. The correct equivalent of your snippet is:Now, when the code is correct, is the time to make it more elegant or fast. For example, you could use an in-memory file-like object instead of file 'trash':
for elegance, a context is best, e.g:
once you have defined this context, for any block in which you don't want a stdout,
More optimization: you just need to replace sys.stdout with an object that has a no-op
write
method. For example:to be used the same way as the previous implementation of
nostdout
. I don't think it gets any cleaner or faster than this;-).Why do you think this is inefficient? Did you test it? By the way, it does not work at all because you are using the
from ... import
statement. Replacingsys.stdout
is fine, but don't make a copy and don't use a temporary file. Open the null device instead:A slight modification to Alex Martelli's answer...
This addresses the case where you always want to suppress
stdout
for a function instead of individual calls to the function.If
foo()
was called many times would it might be better/easier to wrap the function (decorate it). This way you change the definition offoo
once instead of encasing every use of the function in a with-statement.I don't think it gets any cleaner or faster than this;-)
Bah! I think I can do a little better :-D
Which gets to what I wanted originally, to suppress output normally but to show the suppressed output if an error was thrown.
By generalizing even more, you can get a nice decorator that can capture the ouput and even return it: