On 29/09/17 19:06, 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? This makes every *instance* re-entrant. I don't really see the point, but I think this would be a contrived example of such circumstances:
redir_file1 = redirect_stdout(f1) redir_file2 = redirect_stdout(f2) with redir_file1: # do stuff with redir_file2: # Other stuff # Oh no wait actually with redir_file1: # Dum dee dum dee dum pass > > If you use the context manager twice: > > with redirect_stdout(f1) as instance1: > with redirect_stdout(f2) as instance2: > pass > > the two calls will return different instances and sys.stdout will be set as > follows: > > # before first call to redirect_stdout > sys.stdout = __stdout__ # the original setting > > # first call __enter__ > save __stdout__ in instance1._old_targets > set sys.stdout = f1 > > # second call __enter__ > save f1 in instance2._old_targets > set sys.stdout = f2 > > # second call __exit__ > restore sys.stdout = f1 > > # first call __exit__ > restore sys.stdout = __stdout__ > > > I'm not seeing why _old_targets is a list. > > > Can anyone explain? > > -- https://mail.python.org/mailman/listinfo/python-list