##// END OF EJS Templates
Use the default shell to capture shell output....
Pavol Juhas -
Show More
@@ -1,215 +1,217 b''
1 1 """Common utilities for the various process_* implementations.
2 2
3 3 This file is only meant to be imported by the platform-specific implementations
4 4 of subprocess utilities, and it contains tools that are common to all of them.
5 5 """
6 6
7 7 #-----------------------------------------------------------------------------
8 8 # Copyright (C) 2010-2011 The IPython Development Team
9 9 #
10 10 # Distributed under the terms of the BSD License. The full license is in
11 11 # the file COPYING, distributed as part of this software.
12 12 #-----------------------------------------------------------------------------
13 13
14 14 #-----------------------------------------------------------------------------
15 15 # Imports
16 16 #-----------------------------------------------------------------------------
17 17 import subprocess
18 18 import shlex
19 19 import sys
20 import os
20 21
21 22 from IPython.utils import py3compat
22 23
23 24 #-----------------------------------------------------------------------------
24 25 # Function definitions
25 26 #-----------------------------------------------------------------------------
26 27
27 28 def read_no_interrupt(p):
28 29 """Read from a pipe ignoring EINTR errors.
29 30
30 31 This is necessary because when reading from pipes with GUI event loops
31 32 running in the background, often interrupts are raised that stop the
32 33 command from completing."""
33 34 import errno
34 35
35 36 try:
36 37 return p.read()
37 38 except IOError as err:
38 39 if err.errno != errno.EINTR:
39 40 raise
40 41
41 42
42 43 def process_handler(cmd, callback, stderr=subprocess.PIPE):
43 44 """Open a command in a shell subprocess and execute a callback.
44 45
45 46 This function provides common scaffolding for creating subprocess.Popen()
46 47 calls. It creates a Popen object and then calls the callback with it.
47 48
48 49 Parameters
49 50 ----------
50 51 cmd : str or list
51 52 A command to be executed by the system, using :class:`subprocess.Popen`.
52 53 If a string is passed, it will be run in the system shell. If a list is
53 54 passed, it will be used directly as arguments.
54 55
55 56 callback : callable
56 57 A one-argument function that will be called with the Popen object.
57 58
58 59 stderr : file descriptor number, optional
59 60 By default this is set to ``subprocess.PIPE``, but you can also pass the
60 61 value ``subprocess.STDOUT`` to force the subprocess' stderr to go into
61 62 the same file descriptor as its stdout. This is useful to read stdout
62 63 and stderr combined in the order they are generated.
63 64
64 65 Returns
65 66 -------
66 67 The return value of the provided callback is returned.
67 68 """
68 69 sys.stdout.flush()
69 70 sys.stderr.flush()
70 71 # On win32, close_fds can't be true when using pipes for stdin/out/err
71 72 close_fds = sys.platform != 'win32'
72 73 p = subprocess.Popen(cmd, shell=isinstance(cmd, py3compat.string_types),
74 executable=os.environ.get('SHELL'),
73 75 stdin=subprocess.PIPE,
74 76 stdout=subprocess.PIPE,
75 77 stderr=stderr,
76 78 close_fds=close_fds)
77 79
78 80 try:
79 81 out = callback(p)
80 82 except KeyboardInterrupt:
81 83 print('^C')
82 84 sys.stdout.flush()
83 85 sys.stderr.flush()
84 86 out = None
85 87 finally:
86 88 # Make really sure that we don't leave processes behind, in case the
87 89 # call above raises an exception
88 90 # We start by assuming the subprocess finished (to avoid NameErrors
89 91 # later depending on the path taken)
90 92 if p.returncode is None:
91 93 try:
92 94 p.terminate()
93 95 p.poll()
94 96 except OSError:
95 97 pass
96 98 # One last try on our way out
97 99 if p.returncode is None:
98 100 try:
99 101 p.kill()
100 102 except OSError:
101 103 pass
102 104
103 105 return out
104 106
105 107
106 108 def getoutput(cmd):
107 109 """Run a command and return its stdout/stderr as a string.
108 110
109 111 Parameters
110 112 ----------
111 113 cmd : str or list
112 114 A command to be executed in the system shell.
113 115
114 116 Returns
115 117 -------
116 118 output : str
117 119 A string containing the combination of stdout and stderr from the
118 120 subprocess, in whatever order the subprocess originally wrote to its
119 121 file descriptors (so the order of the information in this string is the
120 122 correct order as would be seen if running the command in a terminal).
121 123 """
122 124 out = process_handler(cmd, lambda p: p.communicate()[0], subprocess.STDOUT)
123 125 if out is None:
124 126 return ''
125 127 return py3compat.bytes_to_str(out)
126 128
127 129
128 130 def getoutputerror(cmd):
129 131 """Return (standard output, standard error) of executing cmd in a shell.
130 132
131 133 Accepts the same arguments as os.system().
132 134
133 135 Parameters
134 136 ----------
135 137 cmd : str or list
136 138 A command to be executed in the system shell.
137 139
138 140 Returns
139 141 -------
140 142 stdout : str
141 143 stderr : str
142 144 """
143 145 return get_output_error_code(cmd)[:2]
144 146
145 147 def get_output_error_code(cmd):
146 148 """Return (standard output, standard error, return code) of executing cmd
147 149 in a shell.
148 150
149 151 Accepts the same arguments as os.system().
150 152
151 153 Parameters
152 154 ----------
153 155 cmd : str or list
154 156 A command to be executed in the system shell.
155 157
156 158 Returns
157 159 -------
158 160 stdout : str
159 161 stderr : str
160 162 returncode: int
161 163 """
162 164
163 165 out_err, p = process_handler(cmd, lambda p: (p.communicate(), p))
164 166 if out_err is None:
165 167 return '', '', p.returncode
166 168 out, err = out_err
167 169 return py3compat.bytes_to_str(out), py3compat.bytes_to_str(err), p.returncode
168 170
169 171 def arg_split(s, posix=False, strict=True):
170 172 """Split a command line's arguments in a shell-like manner.
171 173
172 174 This is a modified version of the standard library's shlex.split()
173 175 function, but with a default of posix=False for splitting, so that quotes
174 176 in inputs are respected.
175 177
176 178 if strict=False, then any errors shlex.split would raise will result in the
177 179 unparsed remainder being the last element of the list, rather than raising.
178 180 This is because we sometimes use arg_split to parse things other than
179 181 command-line args.
180 182 """
181 183
182 184 # Unfortunately, python's shlex module is buggy with unicode input:
183 185 # http://bugs.python.org/issue1170
184 186 # At least encoding the input when it's unicode seems to help, but there
185 187 # may be more problems lurking. Apparently this is fixed in python3.
186 188 is_unicode = False
187 189 if (not py3compat.PY3) and isinstance(s, unicode):
188 190 is_unicode = True
189 191 s = s.encode('utf-8')
190 192 lex = shlex.shlex(s, posix=posix)
191 193 lex.whitespace_split = True
192 194 # Extract tokens, ensuring that things like leaving open quotes
193 195 # does not cause this to raise. This is important, because we
194 196 # sometimes pass Python source through this (e.g. %timeit f(" ")),
195 197 # and it shouldn't raise an exception.
196 198 # It may be a bad idea to parse things that are not command-line args
197 199 # through this function, but we do, so let's be safe about it.
198 200 lex.commenters='' #fix for GH-1269
199 201 tokens = []
200 202 while True:
201 203 try:
202 204 tokens.append(next(lex))
203 205 except StopIteration:
204 206 break
205 207 except ValueError:
206 208 if strict:
207 209 raise
208 210 # couldn't parse, get remaining blob as last token
209 211 tokens.append(lex.token)
210 212 break
211 213
212 214 if is_unicode:
213 215 # Convert the tokens back to unicode.
214 216 tokens = [x.decode('utf-8') for x in tokens]
215 217 return tokens
General Comments 0
You need to be logged in to leave comments. Login now