Show More
@@ -0,0 +1,182 b'' | |||
|
1 | { | |
|
2 | "metadata": { | |
|
3 | "name": "Capturing Output" | |
|
4 | }, | |
|
5 | "nbformat": 3, | |
|
6 | "worksheets": [ | |
|
7 | { | |
|
8 | "cells": [ | |
|
9 | { | |
|
10 | "cell_type": "heading", | |
|
11 | "level": 1, | |
|
12 | "source": [ | |
|
13 | "Capturing Output with <tt>%%capture</tt>" | |
|
14 | ] | |
|
15 | }, | |
|
16 | { | |
|
17 | "cell_type": "markdown", | |
|
18 | "source": [ | |
|
19 | "One of IPython's new cell magics is `%%capture`, which captures stdout/err for a cell,", | |
|
20 | "and discards them or stores them in variables in your namespace." | |
|
21 | ] | |
|
22 | }, | |
|
23 | { | |
|
24 | "cell_type": "code", | |
|
25 | "input": [ | |
|
26 | "import sys" | |
|
27 | ], | |
|
28 | "language": "python", | |
|
29 | "outputs": [] | |
|
30 | }, | |
|
31 | { | |
|
32 | "cell_type": "markdown", | |
|
33 | "source": [ | |
|
34 | "By default, it just swallows it up. This is a simple way to suppress unwanted output." | |
|
35 | ] | |
|
36 | }, | |
|
37 | { | |
|
38 | "cell_type": "code", | |
|
39 | "input": [ | |
|
40 | "%%capture", | |
|
41 | "print 'hi, stdout'", | |
|
42 | "print >> sys.stderr, 'hi, stderr'" | |
|
43 | ], | |
|
44 | "language": "python", | |
|
45 | "outputs": [] | |
|
46 | }, | |
|
47 | { | |
|
48 | "cell_type": "markdown", | |
|
49 | "source": [ | |
|
50 | "If you specify a name, then stdout and stderr will be stored in an object in your namespace." | |
|
51 | ] | |
|
52 | }, | |
|
53 | { | |
|
54 | "cell_type": "code", | |
|
55 | "input": [ | |
|
56 | "%%capture captured", | |
|
57 | "print 'hi, stdout'", | |
|
58 | "print >> sys.stderr, 'hi, stderr'" | |
|
59 | ], | |
|
60 | "language": "python", | |
|
61 | "outputs": [] | |
|
62 | }, | |
|
63 | { | |
|
64 | "cell_type": "code", | |
|
65 | "input": [ | |
|
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()" | |
|
81 | ], | |
|
82 | "language": "python", | |
|
83 | "outputs": [] | |
|
84 | }, | |
|
85 | { | |
|
86 | "cell_type": "code", | |
|
87 | "input": [ | |
|
88 | "captured.stdout" | |
|
89 | ], | |
|
90 | "language": "python", | |
|
91 | "outputs": [] | |
|
92 | }, | |
|
93 | { | |
|
94 | "cell_type": "code", | |
|
95 | "input": [ | |
|
96 | "captured.stderr" | |
|
97 | ], | |
|
98 | "language": "python", | |
|
99 | "outputs": [] | |
|
100 | }, | |
|
101 | { | |
|
102 | "cell_type": "markdown", | |
|
103 | "source": [ | |
|
104 | "`%%capture` only captures stdout/err, not displaypub, so you can still do plots and use the display protocol inside %%capture" | |
|
105 | ] | |
|
106 | }, | |
|
107 | { | |
|
108 | "cell_type": "code", | |
|
109 | "input": [ | |
|
110 | "%pylab inline" | |
|
111 | ], | |
|
112 | "language": "python", | |
|
113 | "outputs": [] | |
|
114 | }, | |
|
115 | { | |
|
116 | "cell_type": "code", | |
|
117 | "input": [ | |
|
118 | "%%capture wontshutup", | |
|
119 | "", | |
|
120 | "print \"setting up X\"", | |
|
121 | "x = np.linspace(0,5,1000)", | |
|
122 | "print \"step 2: constructing y-data\"", | |
|
123 | "y = np.sin(x)", | |
|
124 | "print \"step 3: display info about y\"", | |
|
125 | "plt.plot(x,y)", | |
|
126 | "print \"okay, I'm done now\"" | |
|
127 | ], | |
|
128 | "language": "python", | |
|
129 | "outputs": [] | |
|
130 | }, | |
|
131 | { | |
|
132 | "cell_type": "code", | |
|
133 | "input": [ | |
|
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 | "" | |
|
175 | ], | |
|
176 | "language": "python", | |
|
177 | "outputs": [] | |
|
178 | } | |
|
179 | ] | |
|
180 | } | |
|
181 | ] | |
|
182 | } No newline at end of file |
@@ -33,13 +33,15 b' except ImportError:' | |||
|
33 | 33 | |
|
34 | 34 | # Our own packages |
|
35 | 35 | from IPython.core import debugger, oinspect |
|
36 | from IPython.core import magic_arguments | |
|
36 | 37 | from IPython.core import page |
|
37 | 38 | from IPython.core.error import UsageError |
|
38 | 39 | from IPython.core.macro import Macro |
|
39 | from IPython.core.magic import (Magics, magics_class, line_magic, | |
|
40 | from IPython.core.magic import (Magics, magics_class, line_magic, cell_magic, | |
|
40 | 41 | line_cell_magic, on_off, needs_local_scope) |
|
41 | 42 | from IPython.testing.skipdoctest import skip_doctest |
|
42 | 43 | from IPython.utils import py3compat |
|
44 | from IPython.utils.io import capture_output | |
|
43 | 45 | from IPython.utils.ipstruct import Struct |
|
44 | 46 | from IPython.utils.module_paths import find_mod |
|
45 | 47 | from IPython.utils.path import get_py_filename, unquote_filename |
@@ -988,3 +990,33 b' python-profiler package from non-free.""")' | |||
|
988 | 990 | print 'Macro `%s` created. To execute, type its name (without quotes).' % name |
|
989 | 991 | print '=== Macro contents: ===' |
|
990 | 992 | print macro, |
|
993 | ||
|
994 | @magic_arguments.magic_arguments() | |
|
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. | |
|
999 | ||
|
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. | |
|
1003 | ||
|
1004 | If unspecified, captured output is discarded. | |
|
1005 | """ | |
|
1006 | ) | |
|
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 | ) | |
|
1013 | @cell_magic | |
|
1014 | def capture(self, line, cell): | |
|
1015 | """run the cell, capturing stdout/err""" | |
|
1016 | args = magic_arguments.parse_argstring(self.capture, line) | |
|
1017 | out = not args.no_stdout | |
|
1018 | err = not args.no_stderr | |
|
1019 | with capture_output(out, err) as io: | |
|
1020 | self.shell.run_cell(cell) | |
|
1021 | if args.output: | |
|
1022 | self.shell.user_ns[args.output] = io |
@@ -100,36 +100,6 b' def skip_without(*names):' | |||
|
100 | 100 | # Classes |
|
101 | 101 | #------------------------------------------------------------------------------- |
|
102 | 102 | |
|
103 | class CapturedIO(object): | |
|
104 | """Simple object for containing captured stdout/err StringIO objects""" | |
|
105 | ||
|
106 | def __init__(self, stdout, stderr): | |
|
107 | self.stdout_io = stdout | |
|
108 | self.stderr_io = stderr | |
|
109 | ||
|
110 | @property | |
|
111 | def stdout(self): | |
|
112 | return self.stdout_io.getvalue() | |
|
113 | ||
|
114 | @property | |
|
115 | def stderr(self): | |
|
116 | return self.stderr_io.getvalue() | |
|
117 | ||
|
118 | ||
|
119 | class capture_output(object): | |
|
120 | """context manager for capturing stdout/err""" | |
|
121 | ||
|
122 | def __enter__(self): | |
|
123 | self.sys_stdout = sys.stdout | |
|
124 | self.sys_stderr = sys.stderr | |
|
125 | stdout = sys.stdout = StringIO() | |
|
126 | stderr = sys.stderr = StringIO() | |
|
127 | return CapturedIO(stdout, stderr) | |
|
128 | ||
|
129 | def __exit__(self, exc_type, exc_value, traceback): | |
|
130 | sys.stdout = self.sys_stdout | |
|
131 | sys.stderr = self.sys_stderr | |
|
132 | ||
|
133 | 103 | |
|
134 | 104 | class ClusterTestCase(BaseZMQTestCase): |
|
135 | 105 |
@@ -18,11 +18,12 b' Authors:' | |||
|
18 | 18 | |
|
19 | 19 | import time |
|
20 | 20 | |
|
21 |
from IPython. |
|
|
21 | from IPython.utils.io import capture_output | |
|
22 | 22 | |
|
23 | from IPython.parallel.error import TimeoutError | |
|
23 | 24 | from IPython.parallel import error, Client |
|
24 | 25 | from IPython.parallel.tests import add_engines |
|
25 |
from .clienttest import ClusterTestCase |
|
|
26 | from .clienttest import ClusterTestCase | |
|
26 | 27 | |
|
27 | 28 | def setup(): |
|
28 | 29 | add_engines(2, total=True) |
@@ -25,6 +25,7 b' from nose import SkipTest' | |||
|
25 | 25 | |
|
26 | 26 | from IPython.testing import decorators as dec |
|
27 | 27 | from IPython.testing.ipunittest import ParametricTestCase |
|
28 | from IPython.utils.io import capture_output | |
|
28 | 29 | |
|
29 | 30 | from IPython import parallel as pmod |
|
30 | 31 | from IPython.parallel import error |
@@ -33,7 +34,7 b' from IPython.parallel.util import interactive' | |||
|
33 | 34 | |
|
34 | 35 | from IPython.parallel.tests import add_engines |
|
35 | 36 | |
|
36 |
from .clienttest import ClusterTestCase, |
|
|
37 | from .clienttest import ClusterTestCase, generate_output | |
|
37 | 38 | |
|
38 | 39 | def setup(): |
|
39 | 40 | add_engines(3, total=True) |
@@ -17,6 +17,7 b' from __future__ import print_function' | |||
|
17 | 17 | import os |
|
18 | 18 | import sys |
|
19 | 19 | import tempfile |
|
20 | from StringIO import StringIO | |
|
20 | 21 | |
|
21 | 22 | #----------------------------------------------------------------------------- |
|
22 | 23 | # Code |
@@ -321,3 +322,63 b' def raw_print_err(*args, **kw):' | |||
|
321 | 322 | # Short aliases for quick debugging, do NOT use these in production code. |
|
322 | 323 | rprint = raw_print |
|
323 | 324 | rprinte = raw_print_err |
|
325 | ||
|
326 | ||
|
327 | class CapturedIO(object): | |
|
328 | """Simple object for containing captured stdout/err StringIO objects""" | |
|
329 | ||
|
330 | def __init__(self, stdout, stderr): | |
|
331 | self._stdout = stdout | |
|
332 | self._stderr = stderr | |
|
333 | ||
|
334 | def __str__(self): | |
|
335 | return self.stdout | |
|
336 | ||
|
337 | @property | |
|
338 | def stdout(self): | |
|
339 | if not self._stdout: | |
|
340 | return '' | |
|
341 | return self._stdout.getvalue() | |
|
342 | ||
|
343 | @property | |
|
344 | def stderr(self): | |
|
345 | if not self._stderr: | |
|
346 | return '' | |
|
347 | return self._stderr.getvalue() | |
|
348 | ||
|
349 | def show(self): | |
|
350 | """write my output to sys.stdout/err as appropriate""" | |
|
351 | sys.stdout.write(self.stdout) | |
|
352 | sys.stderr.write(self.stderr) | |
|
353 | sys.stdout.flush() | |
|
354 | sys.stderr.flush() | |
|
355 | ||
|
356 | __call__ = show | |
|
357 | ||
|
358 | ||
|
359 | class capture_output(object): | |
|
360 | """context manager for capturing stdout/err""" | |
|
361 | stdout = True | |
|
362 | stderr = True | |
|
363 | ||
|
364 | def __init__(self, stdout=True, stderr=True): | |
|
365 | self.stdout = stdout | |
|
366 | self.stderr = stderr | |
|
367 | ||
|
368 | def __enter__(self): | |
|
369 | self.sys_stdout = sys.stdout | |
|
370 | self.sys_stderr = sys.stderr | |
|
371 | ||
|
372 | stdout = stderr = False | |
|
373 | if self.stdout: | |
|
374 | stdout = sys.stdout = StringIO() | |
|
375 | if self.stderr: | |
|
376 | stderr = sys.stderr = StringIO() | |
|
377 | ||
|
378 | return CapturedIO(stdout, stderr) | |
|
379 | ||
|
380 | def __exit__(self, exc_type, exc_value, traceback): | |
|
381 | sys.stdout = self.sys_stdout | |
|
382 | sys.stderr = self.sys_stderr | |
|
383 | ||
|
384 |
@@ -20,7 +20,7 b' from subprocess import Popen, PIPE' | |||
|
20 | 20 | import nose.tools as nt |
|
21 | 21 | |
|
22 | 22 | from IPython.testing import decorators as dec |
|
23 | from IPython.utils.io import Tee | |
|
23 | from IPython.utils.io import Tee, capture_output | |
|
24 | 24 | from IPython.utils.py3compat import doctest_refactor_print |
|
25 | 25 | |
|
26 | 26 | #----------------------------------------------------------------------------- |
@@ -73,3 +73,13 b' def test_io_init():' | |||
|
73 | 73 | # __class__ is a reference to the class object in Python 3, so we can't |
|
74 | 74 | # just test for string equality. |
|
75 | 75 | assert 'IPython.utils.io.IOStream' in classname, classname |
|
76 | ||
|
77 | def test_capture_output(): | |
|
78 | """capture_output() context works""" | |
|
79 | ||
|
80 | with capture_output() as io: | |
|
81 | print 'hi, stdout' | |
|
82 | print >> sys.stderr, 'hi, stderr' | |
|
83 | ||
|
84 | nt.assert_equals(io.stdout, 'hi, stdout\n') | |
|
85 | nt.assert_equals(io.stderr, 'hi, stderr\n') |
General Comments 0
You need to be logged in to leave comments.
Login now