Skip to content

Commit 34ddebb

Browse files
committed
update capture per review
* capture stores io object, rather than stdout/err text directly * add options to selectively disable capturing stdout/err
1 parent 6897c09 commit 34ddebb

3 files changed

Lines changed: 110 additions & 29 deletions

File tree

IPython/core/magics/execution.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -992,25 +992,31 @@ def macro(self, parameter_s=''):
992992
print macro,
993993

994994
@magic_arguments.magic_arguments()
995-
@magic_arguments.argument('-o', '--out', type=str,
996-
help="""The name of the variable in which to store stdout
995+
@magic_arguments.argument('output', type=str, default='', nargs='?',
996+
help="""The name of the variable in which to store output.
997+
This is a utils.io.CapturedIO object with stdout/err attributes
998+
for the text of the captured output.
997999
998-
If unspecified: stdout is discarded
999-
"""
1000-
)
1001-
@magic_arguments.argument('-e', '--err', type=str,
1002-
help="""The name of the variable in which to store stderr
1000+
CapturedOutput also has a show() method for displaying the output,
1001+
and __call__ as well, so you can use that to quickly display the
1002+
output.
10031003
1004-
If unspecified: stderr is discarded
1004+
If unspecified, captured output is discarded.
10051005
"""
10061006
)
1007+
@magic_arguments.argument('--no-stderr', action="store_true",
1008+
help="""Don't capture stderr."""
1009+
)
1010+
@magic_arguments.argument('--no-stdout', action="store_true",
1011+
help="""Don't capture stdout."""
1012+
)
10071013
@cell_magic
10081014
def capture(self, line, cell):
10091015
"""run the cell, capturing stdout/err"""
10101016
args = magic_arguments.parse_argstring(self.capture, line)
1011-
with capture_output() as io:
1017+
out = not args.no_stdout
1018+
err = not args.no_stderr
1019+
with capture_output(out, err) as io:
10121020
self.shell.run_cell(cell)
1013-
if args.out:
1014-
self.shell.user_ns[args.out] = io.stdout
1015-
if args.err:
1016-
self.shell.user_ns[args.err] = io.stderr
1021+
if args.output:
1022+
self.shell.user_ns[args.output] = io

IPython/utils/io.py

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -328,26 +328,50 @@ class CapturedIO(object):
328328
"""Simple object for containing captured stdout/err StringIO objects"""
329329

330330
def __init__(self, stdout, stderr):
331-
self.stdout_io = stdout
332-
self.stderr_io = stderr
331+
self._stdout = stdout
332+
self._stderr = stderr
333333

334334
@property
335335
def stdout(self):
336-
return self.stdout_io.getvalue()
336+
if not self._stdout:
337+
return ''
338+
return self._stdout.getvalue()
337339

338340
@property
339341
def stderr(self):
340-
return self.stderr_io.getvalue()
342+
if not self._stderr:
343+
return ''
344+
return self._stderr.getvalue()
345+
346+
def show(self):
347+
"""write my output to sys.stdout/err as appropriate"""
348+
sys.stdout.write(self.stdout)
349+
sys.stderr.write(self.stderr)
350+
sys.stdout.flush()
351+
sys.stderr.flush()
352+
353+
__call__ = show
341354

342355

343356
class capture_output(object):
344357
"""context manager for capturing stdout/err"""
358+
stdout = True
359+
stderr = True
360+
361+
def __init__(self, stdout=True, stderr=True):
362+
self.stdout = stdout
363+
self.stderr = stderr
345364

346365
def __enter__(self):
347366
self.sys_stdout = sys.stdout
348367
self.sys_stderr = sys.stderr
349-
stdout = sys.stdout = StringIO()
350-
stderr = sys.stderr = StringIO()
368+
369+
stdout = stderr = False
370+
if self.stdout:
371+
stdout = sys.stdout = StringIO()
372+
if self.stderr:
373+
stderr = sys.stderr = StringIO()
374+
351375
return CapturedIO(stdout, stderr)
352376

353377
def __exit__(self, exc_type, exc_value, traceback):

docs/examples/notebooks/Capturing Output.ipynb

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,13 @@
4747
{
4848
"cell_type": "markdown",
4949
"source": [
50-
"If you specify `-o` or `-e`, then stdout and/or stderr will be stored in those variables in your namespace."
50+
"If you specify a name, then stdout and stderr will be stored in an object in your namespace."
5151
]
5252
},
5353
{
5454
"cell_type": "code",
5555
"input": [
56-
"%%capture -o my_stdout",
56+
"%%capture captured",
5757
"print 'hi, stdout'",
5858
"print >> sys.stderr, 'hi, stderr'"
5959
],
@@ -63,26 +63,37 @@
6363
{
6464
"cell_type": "code",
6565
"input": [
66-
"my_stdout"
66+
"captured"
67+
],
68+
"language": "python",
69+
"outputs": []
70+
},
71+
{
72+
"cell_type": "markdown",
73+
"source": [
74+
"Calling the object writes the output to stdout/err as appropriate."
75+
]
76+
},
77+
{
78+
"cell_type": "code",
79+
"input": [
80+
"captured()"
6781
],
6882
"language": "python",
6983
"outputs": []
7084
},
7185
{
7286
"cell_type": "code",
7387
"input": [
74-
"%%capture -o my_stdout2 -e my_stderr",
75-
"print 'hi again, stdout'",
76-
"print >> sys.stderr, 'hi there, stderr'"
88+
"captured.stdout"
7789
],
7890
"language": "python",
7991
"outputs": []
8092
},
8193
{
8294
"cell_type": "code",
8395
"input": [
84-
"sys.stdout.write(my_stdout2)",
85-
"sys.stderr.write(my_stderr)"
96+
"captured.stderr"
8697
],
8798
"language": "python",
8899
"outputs": []
@@ -104,7 +115,7 @@
104115
{
105116
"cell_type": "code",
106117
"input": [
107-
"%%capture -o wontshutup",
118+
"%%capture wontshutup",
108119
"",
109120
"print \"setting up X\"",
110121
"x = np.linspace(0,5,1000)",
@@ -120,7 +131,47 @@
120131
{
121132
"cell_type": "code",
122133
"input": [
123-
"print wontshutup"
134+
"wontshutup()"
135+
],
136+
"language": "python",
137+
"outputs": []
138+
},
139+
{
140+
"cell_type": "markdown",
141+
"source": [
142+
"And you can selectively disable capturing stdout or stderr by passing `--no-stdout/err`."
143+
]
144+
},
145+
{
146+
"cell_type": "code",
147+
"input": [
148+
"%%capture cap --no-stderr",
149+
"print 'hi, stdout'",
150+
"print >> sys.stderr, \"hello, stderr\""
151+
],
152+
"language": "python",
153+
"outputs": []
154+
},
155+
{
156+
"cell_type": "code",
157+
"input": [
158+
"cap.stdout"
159+
],
160+
"language": "python",
161+
"outputs": []
162+
},
163+
{
164+
"cell_type": "code",
165+
"input": [
166+
"cap.stderr"
167+
],
168+
"language": "python",
169+
"outputs": []
170+
},
171+
{
172+
"cell_type": "code",
173+
"input": [
174+
""
124175
],
125176
"language": "python",
126177
"outputs": []

0 commit comments

Comments
 (0)