Suppress stdout / stderr print from Python functions
This approach (found through the related sidebar) might work. It reassigns the file descriptors rather than just the wrappers to them in sys.stdout, etc.
As of python 3.5 we can do this with minimal work using built-ins in contextlib
, namely redirect_stdout
and redirect_stderr
. We only need to combine these two built-in context managers in a custom context manager of ours, which can be easily done using the nice pattern in Martijn's answer here. Redirecting both outputs to os.devnull
should be safe and portable enough.
from contextlib import contextmanager,redirect_stderr,redirect_stdout
from os import devnull
@contextmanager
def suppress_stdout_stderr():
"""A context manager that redirects stdout and stderr to devnull"""
with open(devnull, 'w') as fnull:
with redirect_stderr(fnull) as err, redirect_stdout(fnull) as out:
yield (err, out)
Note that suppressing stderr
will still give you full tracebacks when something breaks, which is a good thing:
import sys
def rogue_function():
print('spam to stdout')
print('important warning', file=sys.stderr)
1 + 'a'
return 42
with suppress_stdout_stderr():
rogue_function()
When run the above only prints
Traceback (most recent call last):
File "tmp.py", line 20, in <module>
rogue_function()
File "foo.py", line 16, in rogue_function
1 + 'a'
TypeError: unsupported operand type(s) for +: 'int' and 'str'
to the terminal. Unhandled exceptions should never go unnoticed.
python 3.6 working version, tested with million suppressions without any errors
import os
import sys
class suppress_stdout_stderr(object):
def __enter__(self):
self.outnull_file = open(os.devnull, 'w')
self.errnull_file = open(os.devnull, 'w')
self.old_stdout_fileno_undup = sys.stdout.fileno()
self.old_stderr_fileno_undup = sys.stderr.fileno()
self.old_stdout_fileno = os.dup ( sys.stdout.fileno() )
self.old_stderr_fileno = os.dup ( sys.stderr.fileno() )
self.old_stdout = sys.stdout
self.old_stderr = sys.stderr
os.dup2 ( self.outnull_file.fileno(), self.old_stdout_fileno_undup )
os.dup2 ( self.errnull_file.fileno(), self.old_stderr_fileno_undup )
sys.stdout = self.outnull_file
sys.stderr = self.errnull_file
return self
def __exit__(self, *_):
sys.stdout = self.old_stdout
sys.stderr = self.old_stderr
os.dup2 ( self.old_stdout_fileno, self.old_stdout_fileno_undup )
os.dup2 ( self.old_stderr_fileno, self.old_stderr_fileno_undup )
os.close ( self.old_stdout_fileno )
os.close ( self.old_stderr_fileno )
self.outnull_file.close()
self.errnull_file.close()