Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 088cbf2

Browse files
committed
Issue #15805: Add contextlib.redirect_stdout()
1 parent 5ed3bc9 commit 088cbf2

4 files changed

Lines changed: 81 additions & 1 deletion

File tree

Doc/library/contextlib.rst

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,37 @@ Functions and classes provided:
115115

116116
.. versionadded:: 3.4
117117

118+
.. function:: redirect_stdout(new_target)
119+
120+
Context manager for temporarily redirecting :data:`sys.stdout` to
121+
another file or file-like object.
122+
123+
This tool adds flexibility to existing functions or classes whose output
124+
is hardwired to stdout.
125+
126+
For example, the output of :func:`help` normally is sent to *sys.stdout*.
127+
You can capture that output in a string by redirecting the output to a
128+
:class:`io.StringIO` object::
129+
130+
f = io.StringIO()
131+
with redirect_stdout(f):
132+
help(pow)
133+
s = f.getvalue()
134+
135+
To send the output of :func:`help` to a file on disk, redirect the output
136+
to a regular file::
137+
138+
with open('help.txt', 'w') as f:
139+
with redirect_stdout(f):
140+
help(pow)
141+
142+
To send the output of :func:`help` to *sys.stderr*::
143+
144+
with redirect_stdout(sys.stderr):
145+
help(pow)
146+
147+
.. versionadded:: 3.4
148+
118149
.. class:: ContextDecorator()
119150

120151
A base class that enables a context manager to also be used as a decorator.

Lib/contextlib.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
from collections import deque
55
from functools import wraps
66

7-
__all__ = ["contextmanager", "closing", "ContextDecorator", "ExitStack", "ignored"]
7+
__all__ = ["contextmanager", "closing", "ContextDecorator", "ExitStack",
8+
"ignored", "redirect_stdout"]
89

910

1011
class ContextDecorator(object):
@@ -140,6 +141,43 @@ def __enter__(self):
140141
def __exit__(self, *exc_info):
141142
self.thing.close()
142143

144+
class redirect_stdout:
145+
"""Context manager for temporarily redirecting stdout to another file
146+
147+
# How to send help() to stderr
148+
149+
with redirect_stdout(sys.stderr):
150+
help(dir)
151+
152+
# How to write help() to a file
153+
154+
with open('help.txt', 'w') as f:
155+
with redirect_stdout(f):
156+
help(pow)
157+
158+
# How to capture disassembly to a string
159+
160+
import dis
161+
import io
162+
163+
f = io.StringIO()
164+
with redirect_stdout(f):
165+
dis.dis('x**2 - y**2')
166+
s = f.getvalue()
167+
168+
"""
169+
170+
def __init__(self, new_target):
171+
self.new_target = new_target
172+
173+
def __enter__(self):
174+
self.old_target = sys.stdout
175+
sys.stdout = self.new_target
176+
return self.new_target
177+
178+
def __exit__(self, exctype, excinst, exctb):
179+
sys.stdout = self.old_target
180+
143181
@contextmanager
144182
def ignored(*exceptions):
145183
"""Context manager to ignore specified exceptions

Lib/test/test_contextlib.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Unit tests for contextlib.py, and other context managers."""
22

3+
import io
34
import sys
45
import tempfile
56
import unittest
@@ -653,6 +654,14 @@ def test_exception_hierarchy(self):
653654
with ignored(LookupError):
654655
'Hello'[50]
655656

657+
class TestRedirectStdout(unittest.TestCase):
658+
659+
def test_redirect_to_string_io(self):
660+
f = io.StringIO()
661+
with redirect_stdout(f):
662+
help(pow)
663+
s = f.getvalue()
664+
self.assertIn('pow', s)
656665

657666
if __name__ == "__main__":
658667
unittest.main()

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ Library
3232
- Issue #19158: a rare race in BoundedSemaphore could allow .release() too
3333
often.
3434

35+
- Issue #15805: Add contextlib.redirect_stdout().
36+
3537
- Issue #18716: Deprecate the formatter module.
3638

3739
- Issue #18037: 2to3 now escapes '\u' and '\U' in native strings.

0 commit comments

Comments
 (0)