Temporarily Redirect stdout/stderr
You can also put the redirection logic in a contextmanager.
import osimport sysclass RedirectStdStreams(object): def __init__(self, stdout=None, stderr=None): self._stdout = stdout or sys.stdout self._stderr = stderr or sys.stderr def __enter__(self): self.old_stdout, self.old_stderr = sys.stdout, sys.stderr self.old_stdout.flush(); self.old_stderr.flush() sys.stdout, sys.stderr = self._stdout, self._stderr def __exit__(self, exc_type, exc_value, traceback): self._stdout.flush(); self._stderr.flush() sys.stdout = self.old_stdout sys.stderr = self.old_stderrif __name__ == '__main__': devnull = open(os.devnull, 'w') print('Fubar') with RedirectStdStreams(stdout=devnull, stderr=devnull): print("You'll never see me") print("I'm back!")
To solve the issue that some function might have cached sys.stdout
stream as a local variable and therefore replacing the global sys.stdout
won't work inside that function, you could redirect at a file descriptor level (sys.stdout.fileno()
) e.g.:
from __future__ import print_functionimport osimport sysdef some_function_with_cached_sys_stdout(stdout=sys.stdout): print('cached stdout', file=stdout)with stdout_redirected(to=os.devnull), merged_stderr_stdout(): print('stdout goes to devnull') some_function_with_cached_sys_stdout() print('stderr also goes to stdout that goes to devnull', file=sys.stderr)print('stdout is back')some_function_with_cached_sys_stdout()print('stderr is back', file=sys.stderr)
stdout_redirected()
redirects all output for sys.stdout.fileno()
to a given filename, file object, or file descriptor (os.devnull
in the example).
stdout_redirected()
and merged_stderr_stdout()
are defined here.
I am not sure what temporary redirection means. But, you can reassign streams like this and reset it back.
temp = sys.stdoutsys.stdout = sys.stderrsys.stderr = temp
Also to write to sys.stderr within print stmts like this.
print >> sys.stderr, "Error in atexit._run_exitfuncs:"
Regular print will to stdout.