OLD | NEW |
---|---|
1 # Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 """Shared process-related utility functions.""" | 4 """Shared process-related utility functions.""" |
5 | 5 |
6 import errno | 6 import errno |
7 import os | 7 import os |
8 import subprocess | 8 import subprocess |
9 import sys | 9 import sys |
10 | 10 |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
126 Otherwise, prints only the command's stderr to stdout. | 126 Otherwise, prints only the command's stderr to stdout. |
127 | 127 |
128 Returns: | 128 Returns: |
129 The process's exit status. | 129 The process's exit status. |
130 | 130 |
131 Raises: | 131 Raises: |
132 CommandNotFound if the command executable could not be found. | 132 CommandNotFound if the command executable could not be found. |
133 """ | 133 """ |
134 return RunCommandFull(command, verbose)[0] | 134 return RunCommandFull(command, verbose)[0] |
135 | 135 |
136 def RunCommandsInParallel(commands, verbose=True, collect_output=False, | |
137 print_output=True): | |
138 """Runs a list of commands in parallel, waits for all commands to terminate | |
139 and returns their status. If specified, the ouput of commands can be | |
140 returned and/or printed. | |
141 | |
142 Args: | |
143 commands: the list of commands to run, each as a list of one or more | |
144 strings. | |
145 verbose: if True, combines stdout and stderr into stdout. | |
146 Otherwise, prints only the command's stderr to stdout. | |
147 collect_output: if True, collects the output of the each command as a list | |
148 of lines and returns it. | |
149 print_output: if True, prints the output of each command. | |
150 | |
151 Returns: | |
152 A list of tuples consisting of each command's exit status and output. If | |
153 collect_output is False, the output will be []. | |
154 | |
155 Raises: | |
156 CommandNotFound if any of the command executables could not be found. | |
157 """ | |
158 | |
159 command_num = len(commands) | |
160 outputs = [[] for i in xrange(command_num)] | |
161 procs = [None for i in xrange(command_num)] | |
162 eofs = [False for i in xrange(command_num)] | |
163 | |
164 for command in commands: | |
165 print '\n' + subprocess.list2cmdline(command).replace('\\', '/') + '\n', | |
166 | |
167 if verbose: | |
168 out = subprocess.PIPE | |
169 err = subprocess.STDOUT | |
170 else: | |
171 out = file(os.devnull, 'w') | |
172 err = subprocess.PIPE | |
173 | |
174 for i in xrange(command_num): | |
175 try: | |
176 command = commands[i] | |
177 procs[i] = subprocess.Popen(command, stdout=out, stderr=err, bufsize=1) | |
178 except OSError, e: | |
179 if e.errno == errno.ENOENT: | |
180 raise CommandNotFound('Unable to find "%s"' % command[0]) | |
181 raise | |
182 # We could consider terminating the processes already started. | |
183 # But Popen.kill() is only available in version 2.6. | |
184 # For now the clean up is done by KillAll. | |
185 | |
186 while True: | |
187 eof_all = True | |
188 for i in xrange(command_num): | |
189 if eofs[i]: | |
190 continue | |
191 if verbose: | |
192 read_from = procs[i].stdout | |
193 else: | |
194 read_from = procs[i].stderr | |
195 line = read_from.readline() | |
196 if line: | |
197 eof_all = False | |
198 line = line.rstrip() | |
199 outputs[i].append(line) | |
200 if print_output: | |
201 # Windows Python converts \n to \r\n automatically whenever it | |
M-A Ruel
2009/07/29 22:24:46
This looks odd.
sys.stdout.write(line + '\n')
will
| |
202 # encounters it written to a text file (including stdout). The only | |
203 # way around it is to write to a binary file, which isn't feasible | |
204 # for stdout. So we end up with \r\n here even though we explicitly | |
205 # write \n. (We could write \r instead, which doesn't get converted | |
206 # to \r\n, but that's probably more troublesome for people trying to | |
207 # read the files.) | |
208 print line + '\n', | |
209 else: | |
210 eofs[i] = True | |
211 if eof_all: | |
212 break | |
213 | |
214 # Make sure the process terminates. | |
215 for i in xrange(command_num): | |
216 procs[i].wait() | |
217 | |
218 if not verbose: | |
219 out.close() | |
220 | |
221 return [(procs[i].returncode, outputs[i]) for i in xrange(command_num)] | |
OLD | NEW |