X-Git-Url: https://wannabe.guru.org/gitweb/?a=blobdiff_plain;f=exec_utils.py;h=282a325a461e289144b5a58b5a88ce4a90098c83;hb=7c09ecdda0e93da9ffab0d477aa561eb89cd6953;hp=a52e206ad95496ebf4de9eb08f19df8073339d4a;hpb=f83dffe5e1c358ebfee2583f950a42cf7e909969;p=python_utils.git diff --git a/exec_utils.py b/exec_utils.py index a52e206..282a325 100644 --- a/exec_utils.py +++ b/exec_utils.py @@ -12,7 +12,9 @@ from typing import List, Optional logger = logging.getLogger(__file__) -def cmd_showing_output(command: str, ) -> int: +def cmd_showing_output( + command: str, +) -> int: """Kick off a child process. Capture and print all output that it produces on stdout and stderr. Wait for the subprocess to exit and return the exit value as the return code of this function. @@ -30,12 +32,13 @@ def cmd_showing_output(command: str, ) -> int: sel = selectors.DefaultSelector() sel.register(p.stdout, selectors.EVENT_READ) sel.register(p.stderr, selectors.EVENT_READ) - should_exit = False - while not should_exit: + stream_ends = 0 + while stream_ends < 2: for key, _ in sel.select(): char = key.fileobj.read(1) if not char: - should_exit = True + stream_ends += 1 + continue if key.fileobj is p.stdout: sys.stdout.buffer.write(char) if char in line_enders: @@ -45,6 +48,8 @@ def cmd_showing_output(command: str, ) -> int: if char in line_enders: sys.stderr.flush() p.wait() + sys.stdout.flush() + sys.stderr.flush() return p.returncode @@ -63,9 +68,7 @@ def cmd_with_timeout(command: str, timeout_seconds: Optional[float]) -> int: subprocess.TimeoutExpired: Command '['/bin/bash', '-c', '/bin/sleep 2']' timed out after 0.1 seconds """ - return subprocess.check_call( - ["/bin/bash", "-c", command], timeout=timeout_seconds - ) + return subprocess.check_call(["/bin/bash", "-c", command], timeout=timeout_seconds) def cmd(command: str, timeout_seconds: Optional[float] = None) -> str: @@ -115,15 +118,15 @@ def run_silently(command: str, timeout_seconds: Optional[float] = None) -> None: ) -def cmd_in_background( - command: str, *, silent: bool = False -) -> subprocess.Popen: +def cmd_in_background(command: str, *, silent: bool = False) -> subprocess.Popen: args = shlex.split(command) if silent: - subproc = subprocess.Popen(args, - stdin=subprocess.DEVNULL, - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL) + subproc = subprocess.Popen( + args, + stdin=subprocess.DEVNULL, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + ) else: subproc = subprocess.Popen(args, stdin=subprocess.DEVNULL) @@ -135,6 +138,7 @@ def cmd_in_background( subproc.wait(timeout=10.0) except BaseException as be: logger.exception(be) + atexit.register(kill_subproc) return subproc @@ -149,4 +153,5 @@ def cmd_list(command: List[str]) -> str: if __name__ == '__main__': import doctest + doctest.testmod()