diff options
| author | Kevin Van Brunt <kmvanbrunt@gmail.com> | 2019-03-20 10:56:27 -0400 |
|---|---|---|
| committer | Kevin Van Brunt <kmvanbrunt@gmail.com> | 2019-03-20 10:56:27 -0400 |
| commit | e42065ea805c813790ae91dd00e3677ed811c8cd (patch) | |
| tree | 9c59206830eee4d4422c246dfb5f08945cb01fdd /cmd2 | |
| parent | 88f514c956b304407a2426f3da0918673602e3ee (diff) | |
| download | cmd2-git-e42065ea805c813790ae91dd00e3677ed811c8cd.tar.gz | |
Updated ProcReader to determine which of the process streams are pipes
Diffstat (limited to 'cmd2')
| -rw-r--r-- | cmd2/cmd2.py | 13 | ||||
| -rw-r--r-- | cmd2/utils.py | 20 |
2 files changed, 23 insertions, 10 deletions
diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py index 6f0835e0..c33e2927 100644 --- a/cmd2/cmd2.py +++ b/cmd2/cmd2.py @@ -2941,13 +2941,18 @@ class Cmd(cmd.Cmd): expanded_command = ' '.join(tokens) - # If stdout is a StdSim, then we will use pipes so we can save stdout and stderr output - if isinstance(self.stdout, utils.StdSim): - proc = subprocess.Popen(expanded_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) + # For any output that is a StdSim, we will use a pipe so we can save the output + is_out_sim = isinstance(self.stdout, utils.StdSim) + is_err_sim = isinstance(sys.stderr, utils.StdSim) + + proc_stdout = subprocess.PIPE if is_out_sim else self.stdout + proc_stderr = subprocess.PIPE if is_err_sim else sys.stderr + + proc = subprocess.Popen(expanded_command, stdout=proc_stdout, stderr=proc_stderr, shell=True) + if is_out_sim or is_err_sim: proc_reader = utils.ProcReader(proc, self.stdout, sys.stderr) proc_reader.wait() else: - proc = subprocess.Popen(expanded_command, stdout=self.stdout, shell=True) proc.communicate() @staticmethod diff --git a/cmd2/utils.py b/cmd2/utils.py index a0026eba..45c7ca6a 100644 --- a/cmd2/utils.py +++ b/cmd2/utils.py @@ -371,7 +371,7 @@ class ByteBuf(object): class ProcReader(object): - """Used to read stdout and stderr from a Popen process whose stdout and stderr are set to binary pipes""" + """Used to read stdout and stderr from a Popen process if any of those were set to subprocess.PIPE""" def __init__(self, proc: subprocess.Popen, stdout: Union[StdSim, BinaryIO, TextIO], stderr: Union[StdSim, BinaryIO, TextIO]) -> None: """ @@ -390,9 +390,11 @@ class ProcReader(object): self._err_thread = threading.Thread(name='out_thread', target=self._reader_thread_func, kwargs={'read_stdout': False}) - # Start reading from the process - self._out_thread.start() - self._err_thread.start() + # Start the reader threads for pipes only + if self._proc.stdout is not None: + self._out_thread.start() + if self._proc.stderr is not None: + self._err_thread.start() def terminate(self) -> None: """Terminates the process being run""" @@ -400,10 +402,13 @@ class ProcReader(object): def wait(self) -> None: """Wait for the process to finish""" - self._out_thread.join() - self._err_thread.join() + if self._out_thread.is_alive(): + self._out_thread.join() + if self._err_thread.is_alive(): + self._err_thread.join() # Handle case where the process ended before the last read could be done + # This will return None for the streams that weren't pipes so it is safe. out, err = self._proc.communicate() if out: self._write_bytes(self._stdout, out) @@ -422,6 +427,9 @@ class ProcReader(object): read_stream = self._proc.stderr write_stream = self._stderr + # The thread should have been started only if this stream was a pipe + assert read_stream is not None + # Run until process completes while self._proc.poll() is None: # noinspection PyUnresolvedReferences |
