| | """Posix-specific implementation of process utilities. |
| | |
| | This file is only meant to be imported by process.py, not by end-users. |
| | """ |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| |
|
| | |
| | import errno |
| | import os |
| | import subprocess as sp |
| | import sys |
| |
|
| | |
| | from ._process_common import getoutput, arg_split |
| | from IPython.utils.encoding import DEFAULT_ENCODING |
| |
|
| | |
| | |
| | |
| |
|
| | class ProcessHandler(object): |
| | """Execute subprocesses under the control of pexpect. |
| | """ |
| | |
| | |
| | |
| | read_timeout = 0.05 |
| |
|
| | |
| | |
| | terminate_timeout = 0.2 |
| |
|
| | |
| | logfile = None |
| |
|
| | |
| | _sh = None |
| |
|
| | @property |
| | def sh(self): |
| | if self._sh is None: |
| | import pexpect |
| | shell_name = os.environ.get("SHELL", "sh") |
| | self._sh = pexpect.which(shell_name) |
| | if self._sh is None: |
| | raise OSError('"{}" shell not found'.format(shell_name)) |
| |
|
| | return self._sh |
| |
|
| | def __init__(self, logfile=None, read_timeout=None, terminate_timeout=None): |
| | """Arguments are used for pexpect calls.""" |
| | self.read_timeout = (ProcessHandler.read_timeout if read_timeout is |
| | None else read_timeout) |
| | self.terminate_timeout = (ProcessHandler.terminate_timeout if |
| | terminate_timeout is None else |
| | terminate_timeout) |
| | self.logfile = sys.stdout if logfile is None else logfile |
| |
|
| | def getoutput(self, cmd): |
| | """Run a command and return its stdout/stderr as a string. |
| | |
| | Parameters |
| | ---------- |
| | cmd : str |
| | A command to be executed in the system shell. |
| | |
| | Returns |
| | ------- |
| | output : str |
| | A string containing the combination of stdout and stderr from the |
| | subprocess, in whatever order the subprocess originally wrote to its |
| | file descriptors (so the order of the information in this string is the |
| | correct order as would be seen if running the command in a terminal). |
| | """ |
| | import pexpect |
| | try: |
| | return pexpect.run(self.sh, args=['-c', cmd]).replace('\r\n', '\n') |
| | except KeyboardInterrupt: |
| | print('^C', file=sys.stderr, end='') |
| |
|
| | def getoutput_pexpect(self, cmd): |
| | """Run a command and return its stdout/stderr as a string. |
| | |
| | Parameters |
| | ---------- |
| | cmd : str |
| | A command to be executed in the system shell. |
| | |
| | Returns |
| | ------- |
| | output : str |
| | A string containing the combination of stdout and stderr from the |
| | subprocess, in whatever order the subprocess originally wrote to its |
| | file descriptors (so the order of the information in this string is the |
| | correct order as would be seen if running the command in a terminal). |
| | """ |
| | import pexpect |
| | try: |
| | return pexpect.run(self.sh, args=['-c', cmd]).replace('\r\n', '\n') |
| | except KeyboardInterrupt: |
| | print('^C', file=sys.stderr, end='') |
| |
|
| | def system(self, cmd): |
| | """Execute a command in a subshell. |
| | |
| | Parameters |
| | ---------- |
| | cmd : str |
| | A command to be executed in the system shell. |
| | |
| | Returns |
| | ------- |
| | int : child's exitstatus |
| | """ |
| | import pexpect |
| |
|
| | |
| | enc = DEFAULT_ENCODING |
| | |
| | |
| | |
| | patterns = [pexpect.TIMEOUT, pexpect.EOF] |
| | |
| | |
| | |
| | EOF_index = patterns.index(pexpect.EOF) |
| | |
| | |
| | |
| | |
| | out_size = 0 |
| | try: |
| | |
| | |
| | |
| | |
| | |
| | if hasattr(pexpect, 'spawnb'): |
| | child = pexpect.spawnb(self.sh, args=['-c', cmd]) |
| | else: |
| | child = pexpect.spawn(self.sh, args=['-c', cmd]) |
| | flush = sys.stdout.flush |
| | while True: |
| | |
| | |
| | res_idx = child.expect_list(patterns, self.read_timeout) |
| | print(child.before[out_size:].decode(enc, 'replace'), end='') |
| | flush() |
| | if res_idx==EOF_index: |
| | break |
| | |
| | out_size = len(child.before) |
| | except KeyboardInterrupt: |
| | |
| | |
| | |
| | child.sendline(chr(3)) |
| | |
| | |
| | try: |
| | out_size = len(child.before) |
| | child.expect_list(patterns, self.terminate_timeout) |
| | print(child.before[out_size:].decode(enc, 'replace'), end='') |
| | sys.stdout.flush() |
| | except KeyboardInterrupt: |
| | |
| | pass |
| | finally: |
| | |
| | child.terminate(force=True) |
| | |
| | child.isalive() |
| |
|
| | |
| | |
| | |
| | |
| | |
| | if child.exitstatus is None: |
| | |
| | if child.signalstatus is None: |
| | |
| | |
| | return 0 |
| | return -child.signalstatus |
| | if child.exitstatus > 128: |
| | return -(child.exitstatus - 128) |
| | return child.exitstatus |
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | system = ProcessHandler().system |
| |
|
| | def check_pid(pid): |
| | try: |
| | os.kill(pid, 0) |
| | except OSError as err: |
| | if err.errno == errno.ESRCH: |
| | return False |
| | elif err.errno == errno.EPERM: |
| | |
| | return True |
| | raise |
| | else: |
| | return True |
| |
|