I realised making contextlib.redirect_stdout reentrant was actually fairly easy (thread safety is inherently impossible due to the process global side effect). Since making it reentrant makes it more user-friendly, I'll tweak the implementation to work that way.
Need to resolve issue 19330 first, though.
As part of this change, the reusable-but-not-reentrant example in the docs needs to be updated to use contextlib.ExitStack rather than this (that's inherently not reentrant, since all the context managers in the stack would be triggered when the innermost context ends).