Commit 1349002f authored by Raymond Hettinger's avatar Raymond Hettinger

Issue #15805: Add contextlib.redirect_stdout()

parent 340722a9
...@@ -115,6 +115,37 @@ Functions and classes provided: ...@@ -115,6 +115,37 @@ Functions and classes provided:
.. versionadded:: 3.4 .. versionadded:: 3.4
.. function:: redirect_stdout(new_target)
Context manager for temporarily redirecting :data:`sys.stdout` to
another file or file-like object.
This tool adds flexibility to existing functions or classes whose output
is hardwired to stdout.
For example, the output of :func:`help` normally is sent to *sys.stdout*.
You can capture that output in a string by redirecting the output to a
:class:`io.StringIO` object::
f = io.StringIO()
with redirect_stdout(f):
help(pow)
s = f.getvalue()
To send the output of :func:`help` to a file on disk, redirect the output
to a regular file::
with open('help.txt', 'w') as f:
with redirect_stdout(f):
help(pow)
To send the output of :func:`help` to *sys.stderr*::
with redirect_stdout(sys.stderr):
help(pow)
.. versionadded:: 3.4
.. class:: ContextDecorator() .. class:: ContextDecorator()
A base class that enables a context manager to also be used as a decorator. A base class that enables a context manager to also be used as a decorator.
......
...@@ -4,7 +4,8 @@ import sys ...@@ -4,7 +4,8 @@ import sys
from collections import deque from collections import deque
from functools import wraps from functools import wraps
__all__ = ["contextmanager", "closing", "ContextDecorator", "ExitStack", "ignored"] __all__ = ["contextmanager", "closing", "ContextDecorator", "ExitStack",
"ignored", "redirect_stdout"]
class ContextDecorator(object): class ContextDecorator(object):
...@@ -140,6 +141,43 @@ class closing(object): ...@@ -140,6 +141,43 @@ class closing(object):
def __exit__(self, *exc_info): def __exit__(self, *exc_info):
self.thing.close() self.thing.close()
class redirect_stdout:
"""Context manager for temporarily redirecting stdout to another file
# How to send help() to stderr
with redirect_stdout(sys.stderr):
help(dir)
# How to write help() to a file
with open('help.txt', 'w') as f:
with redirect_stdout(f):
help(pow)
# How to capture disassembly to a string
import dis
import io
f = io.StringIO()
with redirect_stdout(f):
dis.dis('x**2 - y**2')
s = f.getvalue()
"""
def __init__(self, new_target):
self.new_target = new_target
def __enter__(self):
self.old_target = sys.stdout
sys.stdout = self.new_target
return self.new_target
def __exit__(self, exctype, excinst, exctb):
sys.stdout = self.old_target
@contextmanager @contextmanager
def ignored(*exceptions): def ignored(*exceptions):
"""Context manager to ignore specified exceptions """Context manager to ignore specified exceptions
......
"""Unit tests for contextlib.py, and other context managers.""" """Unit tests for contextlib.py, and other context managers."""
import io
import sys import sys
import tempfile import tempfile
import unittest import unittest
...@@ -653,6 +654,14 @@ class TestIgnored(unittest.TestCase): ...@@ -653,6 +654,14 @@ class TestIgnored(unittest.TestCase):
with ignored(LookupError): with ignored(LookupError):
'Hello'[50] 'Hello'[50]
class TestRedirectStdout(unittest.TestCase):
def test_redirect_to_string_io(self):
f = io.StringIO()
with redirect_stdout(f):
help(pow)
s = f.getvalue()
self.assertIn('pow', s)
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()
...@@ -32,6 +32,8 @@ Library ...@@ -32,6 +32,8 @@ Library
- Issue #19158: a rare race in BoundedSemaphore could allow .release() too - Issue #19158: a rare race in BoundedSemaphore could allow .release() too
often. often.
- Issue #15805: Add contextlib.redirect_stdout().
- Issue #18716: Deprecate the formatter module. - Issue #18716: Deprecate the formatter module.
- Issue #18037: 2to3 now escapes '\u' and '\U' in native strings. - Issue #18037: 2to3 now escapes '\u' and '\U' in native strings.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment