|
7 | 7 | import shutil |
8 | 8 | import subprocess |
9 | 9 | import sys |
| 10 | +import threading |
10 | 11 |
|
11 | 12 | if sys.platform.startswith('linux'): |
12 | 13 | sys_platform = 'linux' |
@@ -127,20 +128,55 @@ def distutils_exec_process(cmdline, silent=True, input=None, **kwargs): |
127 | 128 | Optionally prints stdout and stderr while running.""" |
128 | 129 |
|
129 | 130 | try: |
130 | | - sub = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs) |
131 | | - stdout, stderr = sub.communicate(input=input) |
132 | | - returncode = sub.returncode |
133 | | - if not silent: |
134 | | - sys.stdout.write(stdout.decode()) |
135 | | - sys.stderr.write(stderr.decode()) |
| 131 | + sub = subprocess.Popen( |
| 132 | + cmdline, |
| 133 | + stdin=subprocess.PIPE, |
| 134 | + stdout=subprocess.PIPE, |
| 135 | + stderr=subprocess.PIPE, |
| 136 | + bufsize=1, # Line-buffered |
| 137 | + text=True, # Automatically decode to str |
| 138 | + **kwargs |
| 139 | + ) |
| 140 | + |
| 141 | + stdout_lines = [] |
| 142 | + stderr_lines = [] |
| 143 | + |
| 144 | + def read_stream(stream, collector, writer): |
| 145 | + for line in stream: |
| 146 | + collector.append(line) |
| 147 | + if not silent and writer: |
| 148 | + writer.write(line) |
| 149 | + writer.flush() |
| 150 | + |
| 151 | + threads = [] |
| 152 | + threads.append(threading.Thread(target=read_stream, args=(sub.stdout, stdout_lines, sys.stdout))) |
| 153 | + threads.append(threading.Thread(target=read_stream, args=(sub.stderr, stderr_lines, sys.stderr))) |
| 154 | + |
| 155 | + for t in threads: |
| 156 | + t.start() |
| 157 | + |
| 158 | + if input: |
| 159 | + sub.stdin.write(input) |
| 160 | + sub.stdin.close() |
| 161 | + |
| 162 | + for t in threads: |
| 163 | + t.join() |
| 164 | + |
| 165 | + returncode = sub.wait() |
| 166 | + |
136 | 167 | except OSError as e: |
137 | 168 | if e.errno == errno.ENOENT: |
138 | | - raise RuntimeError('"%s" is not present on this system' % cmdline[0]) |
| 169 | + raise RuntimeError(f'"{cmdline[0]}" is not present on this system') |
139 | 170 | else: |
140 | 171 | raise |
| 172 | + |
141 | 173 | if returncode != 0: |
142 | | - raise RuntimeError('Got return value %d while executing "%s", stderr output was:\n%s' % (returncode, " ".join(cmdline), stderr.decode())) |
143 | | - return stdout.decode() |
| 174 | + raise RuntimeError( |
| 175 | + f'Got return value {returncode} while executing "{" ".join(cmdline)}", ' |
| 176 | + f'stderr output was:\n{"".join(stderr_lines)}' |
| 177 | + ) |
| 178 | + |
| 179 | + return "".join(stdout_lines) |
144 | 180 |
|
145 | 181 | @staticmethod |
146 | 182 | def get_make_cmd(): |
|
0 commit comments