##// END OF EJS Templates
Merge pull request #1870 from minrk/captureio...
Fernando Perez -
r7411:024e3846 merge
parent child Browse files
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.parallel.error import TimeoutError
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, capture_output
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, capture_output, generate_output
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