Open a command in a shell subprocess and execute a callback. This function provides common scaffolding for creating subprocess.Popen() calls. It creates a Popen object and then calls the callback with it. Parameters ---------- cmd : str or list A command to be executed
(
cmd: Union[str, List[str]],
callback: Callable[[subprocess.Popen[bytes]], _T],
stderr: int = subprocess.PIPE,
)
| 46 | |
| 47 | |
| 48 | def process_handler( |
| 49 | cmd: Union[str, List[str]], |
| 50 | callback: Callable[[subprocess.Popen[bytes]], _T], |
| 51 | stderr: int = subprocess.PIPE, |
| 52 | ) -> _T | None: |
| 53 | """Open a command in a shell subprocess and execute a callback. |
| 54 | |
| 55 | This function provides common scaffolding for creating subprocess.Popen() |
| 56 | calls. It creates a Popen object and then calls the callback with it. |
| 57 | |
| 58 | Parameters |
| 59 | ---------- |
| 60 | cmd : str or list |
| 61 | A command to be executed by the system, using :class:`subprocess.Popen`. |
| 62 | If a string is passed, it will be run in the system shell. If a list is |
| 63 | passed, it will be used directly as arguments. |
| 64 | callback : callable |
| 65 | A one-argument function that will be called with the Popen object. |
| 66 | stderr : file descriptor number, optional |
| 67 | By default this is set to ``subprocess.PIPE``, but you can also pass the |
| 68 | value ``subprocess.STDOUT`` to force the subprocess' stderr to go into |
| 69 | the same file descriptor as its stdout. This is useful to read stdout |
| 70 | and stderr combined in the order they are generated. |
| 71 | |
| 72 | Returns |
| 73 | ------- |
| 74 | The return value of the provided callback is returned. |
| 75 | """ |
| 76 | sys.stdout.flush() |
| 77 | sys.stderr.flush() |
| 78 | # On win32, close_fds can't be true when using pipes for stdin/out/err |
| 79 | if sys.platform == "win32" and stderr != subprocess.PIPE: |
| 80 | close_fds = False |
| 81 | else: |
| 82 | close_fds = True |
| 83 | # Determine if cmd should be run with system shell. |
| 84 | shell = isinstance(cmd, str) |
| 85 | # On POSIX systems run shell commands with user-preferred shell. |
| 86 | executable = None |
| 87 | if shell and os.name == 'posix' and 'SHELL' in os.environ: |
| 88 | executable = os.environ['SHELL'] |
| 89 | p = subprocess.Popen(cmd, shell=shell, |
| 90 | executable=executable, |
| 91 | stdin=subprocess.PIPE, |
| 92 | stdout=subprocess.PIPE, |
| 93 | stderr=stderr, |
| 94 | close_fds=close_fds) |
| 95 | |
| 96 | try: |
| 97 | out = callback(p) |
| 98 | except KeyboardInterrupt: |
| 99 | print('^C') |
| 100 | sys.stdout.flush() |
| 101 | sys.stderr.flush() |
| 102 | out = None |
| 103 | finally: |
| 104 | # Make really sure that we don't leave processes behind, in case the |
| 105 | # call above raises an exception |
no test coverage detected
searching dependent graphs…