Silence the stdout of a function in Python without trashing sys.stdout and restoring each function call

Assigning the stdout variable as you're doing has no effect whatsoever, assuming foo contains print 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). The copy is irrelevant, by the way. The correct equivalent of your snippet is:

import sys
save_stdout = sys.stdout
sys.stdout = open('trash', 'w')
foo()
sys.stdout = save_stdout

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':

import sys
import io
save_stdout = sys.stdout
sys.stdout = io.BytesIO()
foo()
sys.stdout = save_stdout

for elegance, a context is best, e.g:

import contextlib
import io
import sys

@contextlib.contextmanager
def nostdout():
    save_stdout = sys.stdout
    sys.stdout = io.BytesIO()
    yield
    sys.stdout = save_stdout

once you have defined this context, for any block in which you don't want a stdout,

with nostdout():
    foo()

More optimization: you just need to replace sys.stdout with an object that has a no-op write method. For example:

import contextlib
import sys

class DummyFile(object):
    def write(self, x): pass

@contextlib.contextmanager
def nostdout():
    save_stdout = sys.stdout
    sys.stdout = DummyFile()
    yield
    sys.stdout = save_stdout

to be used the same way as the previous implementation of nostdout. I don't think it gets any cleaner or faster than this;-).


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:

In [11]: def f(): print('noise')

In [12]: import os, contextlib

In [13]: with open(os.devnull, 'w') as devnull:
   ....:     with contextlib.redirect_stdout(devnull):
   ....:         f()
   ....:         

In [14]: 

This solution can be adapted to be used as a decorator:

import os, contextlib

def supress_stdout(func):
    def wrapper(*a, **ka):
        with open(os.devnull, 'w') as devnull:
            with contextlib.redirect_stdout(devnull):
                return func(*a, **ka)
    return wrapper

@supress_stdout
def f():
    print('noise')

f() # nothing is printed

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 the file argument of the print function:

In [14]: def f(target): print('noise', file=target)

In [15]: with open(os.devnull, 'w') as devnull:
   ....:     f(target=devnull)
   ....:     

In [16]: 

You can even make target completely optional:

def f(target=sys.stdout):
    # Here goes the function definition

Note, you'll need to

from __future__ import print_function

in Python 2.


Chiming in very late to this with what I thought was a cleaner solution to this problem.

import sys, traceback

class Suppressor(object):

    def __enter__(self):
        self.stdout = sys.stdout
        sys.stdout = self

    def __exit__(self, type, value, traceback):
        sys.stdout = self.stdout
        if type is not None:
            # Do normal exception handling

    def write(self, x): pass

Usage:

with Suppressor():
    DoMyFunction(*args,**kwargs)

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. Replacing sys.stdout is fine, but don't make a copy and don't use a temporary file. Open the null device instead:

import sys
import os

def foo():
    print "abc"

old_stdout = sys.stdout
sys.stdout = open(os.devnull, "w")
try:
    foo()
finally:
    sys.stdout.close()
    sys.stdout = old_stdout

redirect_stdout() has been added to contextlib since python 3.4

For python >= 3.4, this should do it:

import contextlib
import io

with contextlib.redirect_stdout(io.StringIO()):
    foo()