Execute a command in a subshell. Parameters ---------- cmd : str A command to be executed in the system shell. Returns ------- int : child's exitstatus
(self, cmd)
| 119 | print('^C', file=sys.stderr, end='') |
| 120 | |
| 121 | def system(self, cmd): |
| 122 | """Execute a command in a subshell. |
| 123 | |
| 124 | Parameters |
| 125 | ---------- |
| 126 | cmd : str |
| 127 | A command to be executed in the system shell. |
| 128 | |
| 129 | Returns |
| 130 | ------- |
| 131 | int : child's exitstatus |
| 132 | """ |
| 133 | # Get likely encoding for the output. |
| 134 | enc = DEFAULT_ENCODING |
| 135 | |
| 136 | # Patterns to match on the output, for pexpect. We read input and |
| 137 | # allow either a short timeout or EOF |
| 138 | patterns = [pexpect.TIMEOUT, pexpect.EOF] |
| 139 | # the index of the EOF pattern in the list. |
| 140 | # even though we know it's 1, this call means we don't have to worry if |
| 141 | # we change the above list, and forget to change this value: |
| 142 | EOF_index = patterns.index(pexpect.EOF) |
| 143 | # The size of the output stored so far in the process output buffer. |
| 144 | # Since pexpect only appends to this buffer, each time we print we |
| 145 | # record how far we've printed, so that next time we only print *new* |
| 146 | # content from the buffer. |
| 147 | out_size = 0 |
| 148 | try: |
| 149 | # Since we're not really searching the buffer for text patterns, we |
| 150 | # can set pexpect's search window to be tiny and it won't matter. |
| 151 | # We only search for the 'patterns' timeout or EOF, which aren't in |
| 152 | # the text itself. |
| 153 | #child = pexpect.spawn(pcmd, searchwindowsize=1) |
| 154 | if hasattr(pexpect, 'spawnb'): |
| 155 | child = pexpect.spawnb(self.sh, args=['-c', cmd]) # Pexpect-U |
| 156 | else: |
| 157 | child = pexpect.spawn(self.sh, args=['-c', cmd]) # Vanilla Pexpect |
| 158 | flush = sys.stdout.flush |
| 159 | while True: |
| 160 | # res is the index of the pattern that caused the match, so we |
| 161 | # know whether we've finished (if we matched EOF) or not |
| 162 | res_idx = child.expect_list(patterns, self.read_timeout) |
| 163 | print(child.before[out_size:].decode(enc, 'replace'), end='') |
| 164 | flush() |
| 165 | if res_idx==EOF_index: |
| 166 | break |
| 167 | # Update the pointer to what we've already printed |
| 168 | out_size = len(child.before) |
| 169 | except KeyboardInterrupt: |
| 170 | # We need to send ^C to the process. The ascii code for '^C' is 3 |
| 171 | # (the character is known as ETX for 'End of Text', see |
| 172 | # curses.ascii.ETX). |
| 173 | child.sendline(chr(3)) |
| 174 | # Read and print any more output the program might produce on its |
| 175 | # way out. |
| 176 | try: |
| 177 | out_size = len(child.before) |
| 178 | child.expect_list(patterns, self.terminate_timeout) |