Runs the process, using the provided functions for I/O. The function stdin_func should return strings whenever a character or characters become available. The functions stdout_func and stderr_func are called whenever something is printed to stdout or stderr, respecti
(self, stdout_func = None, stdin_func = None, stderr_func = None)
| 391 | func(s.decode('utf_8', 'replace')) |
| 392 | |
| 393 | def run(self, stdout_func = None, stdin_func = None, stderr_func = None): |
| 394 | """Runs the process, using the provided functions for I/O. |
| 395 | |
| 396 | The function stdin_func should return strings whenever a |
| 397 | character or characters become available. |
| 398 | The functions stdout_func and stderr_func are called whenever |
| 399 | something is printed to stdout or stderr, respectively. |
| 400 | These functions are called from different threads (but not |
| 401 | concurrently, because of the GIL). |
| 402 | """ |
| 403 | if stdout_func is None and stdin_func is None and stderr_func is None: |
| 404 | return self._run_stdio() |
| 405 | |
| 406 | if stderr_func is not None and self.mergeout: |
| 407 | raise RuntimeError("Shell command was initiated with " |
| 408 | "merged stdin/stdout, but a separate stderr_func " |
| 409 | "was provided to the run() method") |
| 410 | |
| 411 | # Create a thread for each input/output handle |
| 412 | stdin_thread = None |
| 413 | threads = [] |
| 414 | if stdin_func: |
| 415 | stdin_thread = threading.Thread(target=self._stdin_thread, |
| 416 | args=(self.hstdin, self.piProcInfo.hProcess, |
| 417 | stdin_func, stdout_func)) |
| 418 | threads.append(threading.Thread(target=self._stdout_thread, |
| 419 | args=(self.hstdout, stdout_func))) |
| 420 | if not self.mergeout: |
| 421 | if stderr_func is None: |
| 422 | stderr_func = stdout_func |
| 423 | threads.append(threading.Thread(target=self._stdout_thread, |
| 424 | args=(self.hstderr, stderr_func))) |
| 425 | # Start the I/O threads and the process |
| 426 | if ResumeThread(self.piProcInfo.hThread) == 0xFFFFFFFF: |
| 427 | raise ctypes.WinError() |
| 428 | if stdin_thread is not None: |
| 429 | stdin_thread.start() |
| 430 | for thread in threads: |
| 431 | thread.start() |
| 432 | # Wait for the process to complete |
| 433 | if WaitForSingleObject(self.piProcInfo.hProcess, INFINITE) == \ |
| 434 | WAIT_FAILED: |
| 435 | raise ctypes.WinError() |
| 436 | # Wait for the I/O threads to complete |
| 437 | for thread in threads: |
| 438 | thread.join() |
| 439 | |
| 440 | # Wait for the stdin thread to complete |
| 441 | if stdin_thread is not None: |
| 442 | stdin_thread.join() |
| 443 | |
| 444 | def _stdin_raw_nonblock(self): |
| 445 | """Use the raw Win32 handle of sys.stdin to do non-blocking reads""" |
no test coverage detected