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 | # Our own packages |
|
34 | # Our own packages | |
35 | from IPython.core import debugger, oinspect |
|
35 | from IPython.core import debugger, oinspect | |
|
36 | from IPython.core import magic_arguments | |||
36 | from IPython.core import page |
|
37 | from IPython.core import page | |
37 | from IPython.core.error import UsageError |
|
38 | from IPython.core.error import UsageError | |
38 | from IPython.core.macro import Macro |
|
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 | line_cell_magic, on_off, needs_local_scope) |
|
41 | line_cell_magic, on_off, needs_local_scope) | |
41 | from IPython.testing.skipdoctest import skip_doctest |
|
42 | from IPython.testing.skipdoctest import skip_doctest | |
42 | from IPython.utils import py3compat |
|
43 | from IPython.utils import py3compat | |
|
44 | from IPython.utils.io import capture_output | |||
43 | from IPython.utils.ipstruct import Struct |
|
45 | from IPython.utils.ipstruct import Struct | |
44 | from IPython.utils.module_paths import find_mod |
|
46 | from IPython.utils.module_paths import find_mod | |
45 | from IPython.utils.path import get_py_filename, unquote_filename |
|
47 | from IPython.utils.path import get_py_filename, unquote_filename | |
@@ -988,3 +990,33 b' python-profiler package from non-free.""")' | |||||
988 | print 'Macro `%s` created. To execute, type its name (without quotes).' % name |
|
990 | print 'Macro `%s` created. To execute, type its name (without quotes).' % name | |
989 | print '=== Macro contents: ===' |
|
991 | print '=== Macro contents: ===' | |
990 | print macro, |
|
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 | # Classes |
|
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 | class ClusterTestCase(BaseZMQTestCase): |
|
104 | class ClusterTestCase(BaseZMQTestCase): | |
135 |
|
105 |
@@ -18,11 +18,12 b' Authors:' | |||||
18 |
|
18 | |||
19 | import time |
|
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 | from IPython.parallel import error, Client |
|
24 | from IPython.parallel import error, Client | |
24 | from IPython.parallel.tests import add_engines |
|
25 | from IPython.parallel.tests import add_engines | |
25 |
from .clienttest import ClusterTestCase |
|
26 | from .clienttest import ClusterTestCase | |
26 |
|
27 | |||
27 | def setup(): |
|
28 | def setup(): | |
28 | add_engines(2, total=True) |
|
29 | add_engines(2, total=True) |
@@ -25,6 +25,7 b' from nose import SkipTest' | |||||
25 |
|
25 | |||
26 | from IPython.testing import decorators as dec |
|
26 | from IPython.testing import decorators as dec | |
27 | from IPython.testing.ipunittest import ParametricTestCase |
|
27 | from IPython.testing.ipunittest import ParametricTestCase | |
|
28 | from IPython.utils.io import capture_output | |||
28 |
|
29 | |||
29 | from IPython import parallel as pmod |
|
30 | from IPython import parallel as pmod | |
30 | from IPython.parallel import error |
|
31 | from IPython.parallel import error | |
@@ -33,7 +34,7 b' from IPython.parallel.util import interactive' | |||||
33 |
|
34 | |||
34 | from IPython.parallel.tests import add_engines |
|
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 | def setup(): |
|
39 | def setup(): | |
39 | add_engines(3, total=True) |
|
40 | add_engines(3, total=True) |
@@ -17,6 +17,7 b' from __future__ import print_function' | |||||
17 | import os |
|
17 | import os | |
18 | import sys |
|
18 | import sys | |
19 | import tempfile |
|
19 | import tempfile | |
|
20 | from StringIO import StringIO | |||
20 |
|
21 | |||
21 | #----------------------------------------------------------------------------- |
|
22 | #----------------------------------------------------------------------------- | |
22 | # Code |
|
23 | # Code | |
@@ -321,3 +322,63 b' def raw_print_err(*args, **kw):' | |||||
321 | # Short aliases for quick debugging, do NOT use these in production code. |
|
322 | # Short aliases for quick debugging, do NOT use these in production code. | |
322 | rprint = raw_print |
|
323 | rprint = raw_print | |
323 | rprinte = raw_print_err |
|
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 | import nose.tools as nt |
|
20 | import nose.tools as nt | |
21 |
|
21 | |||
22 | from IPython.testing import decorators as dec |
|
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 | from IPython.utils.py3compat import doctest_refactor_print |
|
24 | from IPython.utils.py3compat import doctest_refactor_print | |
25 |
|
25 | |||
26 | #----------------------------------------------------------------------------- |
|
26 | #----------------------------------------------------------------------------- | |
@@ -73,3 +73,13 b' def test_io_init():' | |||||
73 | # __class__ is a reference to the class object in Python 3, so we can't |
|
73 | # __class__ is a reference to the class object in Python 3, so we can't | |
74 | # just test for string equality. |
|
74 | # just test for string equality. | |
75 | assert 'IPython.utils.io.IOStream' in classname, classname |
|
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