语境:
我有一些使用 编写的代码pexpect
,其工作是提供命令的“实时”输出。即当命令生成一些输出时或不久之后打印一些东西,而不是等到命令完成然后与它的输出交互。
我所做的只是启动和停止服务。我通过spawn
ing 进程来做到这一点,然后在打印时输出每一行,如下所示:
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")
这段代码应该只是循环服务:一遍又一遍地启动和停止它,打印启动/停止的输出。它可以很好地打印输出。但是,它最终会在“OUT 2”之前挂起。我可以查看输出,并看到service
调用停止执行。但是,该watch
函数永远不会引发 EOF 并退出。
并非每项服务都会发生这种情况。一些服务无限循环。zend-server
但是,与其他一些不相关的命令一起,以相同的方式间歇性地失败。
通过“最终挂起”,我的意思是它启动/停止服务几次(每次运行时可变),然后挂起。它通常在 4 到 6 点后起泡,但从来没有在第一次通话时出现 - 至少在第二次通话时(因此del
声明;我想我会稳妥行事)。
Python 2.6.6、CentOS (64) 6.3、Pexpect 2.3-6、FWIW
问题:
为什么pexpect
挂在某些命令上?我应该如何解决这个问题?使用超时不是一个可行的解决方案,因为其中一些命令确实可以运行任意长时间。service zend-server stop
只是我选择的一个例子,因为它不需要那么长时间,我可以观察它完成。
我试过的:
我尝试用以下方法替换该watch
方法,该方法使用expect('\n')
,但结果是相同的:重启次数可变,然后最终挂起。
我也可以添加pexpect.EOF
到与expect
一起编辑的数组中\n
,并处理返回值以跳出循环,它仍然挂在同一个地方。
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