Steve D'Aprano wrote: > In the standard library's contextlib.py module, there is a class for > redirecting standard I/O streams, and two public functions. The code is > short enough to reproduce here: > > # From Python 3.5 > > class _RedirectStream: > _stream = None > def __init__(self, new_target): > self._new_target = new_target > # We use a list of old targets to make this CM re-entrant > self._old_targets = [] > def __enter__(self): > self._old_targets.append(getattr(sys, self._stream)) > setattr(sys, self._stream, self._new_target) > return self._new_target > def __exit__(self, exctype, excinst, exctb): > setattr(sys, self._stream, self._old_targets.pop()) > > class redirect_stdout(_RedirectStream): > # docstring removed > _stream = "stdout" > > class redirect_stderr(_RedirectStream): > # docstring removed > _stream = "stderr" > > > > I don't understand the comment "We use a list of old targets to make this > CM re-entrant". Under what circumstances will there ever be more than a > single entry in _old_targets? > > If you use the context manager twice: > > with redirect_stdout(f1) as instance1: > with redirect_stdout(f2) as instance2: > pass
That's the sane approach, but I just learned that you can reuse a single instance: >>> here = io.StringIO() >>> there = io.StringIO() >>> h = redirect_stdout(here) >>> t = redirect_stdout(there) >>> with h: ... print("ham") ... with t: ... print("foo") ... with h: ... print("spam") ... with t: ... print("bar") ... >>> here.getvalue() 'ham\nspam\n' >>> there.getvalue() 'foo\nbar\n' -- https://mail.python.org/mailman/listinfo/python-list