Context:
I have code written using pexpect , whose task is to give a "live" output to the command. That is, print something when the command generates some output or shortly afterwards, and does not wait until the command completes, and then interacts with its output.
All I do is start and stop the service. I do this using the spawn process, and then outputting each line when printing as follows:
def watch(process): output = "" while True: try: line = process.read_nonblocking(timeout = -1) print(line, end ="") output += line except pexpect.EOF: break del process return output while True: print("IN 1") process = pexpect.spawn("service",["zend-server", "stop"], timeout = None) watch(process) print("OUT 1") print("IN 2") process = pexpect.spawn("service",["zend-server", "start"], timeout = None) watch(process) print("OUT 2")
This code should simply loop the service: start it and stop it again and again, printing the start / stop output as it appears. It prints the output. However, it ends up hanging right in front of "OUT 2". I can view the output and see how the service call stops it. However, the watch function never raises EOF and does not exit.
This does not happen with every service. Some services work endlessly. zend-server , however, along with several other unrelated commands, breaks intermittently in the same way.
"Ultimately hangs," I mean, it starts / stops the service several times (by the variables in each run) and hangs. Usually it rises after 4-6, although never on the first call - always, at least on the second (therefore, in the del expression, I decided that I would play it safely).
Python 2.6.6, CentOS (64) 6.3, Pexpect 2.3-6, FWIW
Question:
Why pexpect hang on certain commands? How do I solve this problem? Using timeouts is not a possible solution, as some of these commands can indeed be executed for an arbitrarily long time. service zend-server stop is the one that I have chosen as an example, because it is not so long and I can observe its completion.
What I tried:
I tried to replace the watch method with the following that uses expect('\n') , but the results are the same: a variable restart number, and then a possible hang.
I can also add pexpect.EOF to the array that expect ed along with \n and process the return value to break out of the loop, it still hangs in one place.
def watch2(process): output = "" done = False while True: try: if not process.isalive(): line = process.readline() done = True else: process.expect(['\n']) line = process.before print(line) output += line if done: raise pexpect.EOF(0) except pexpect.EOF: break del process return output