为什么Pexpect在执行某些命令后会间歇性地挂起(不检测EOF)?

时间:2012-09-28 20:49:36

标签: python spawn pexpect

上下文

我有一些使用pexpect编写的代码,其作用是给出命令的“实时”输出。即当命令生成一些输出时或不久之后打印出来的东西,而不是等到命令完成然后与其输出交互。

我正在做的就是启动和停止服务。我通过spawn进程执行此操作,然后在打印时输出每一行,如下所示:

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

1 个答案:

答案 0 :(得分:3)

看起来像一个缓冲问题,其中pexpect正在等待更多数据。您可以尝试通过将maxread=1传递给pexpect.spawn()

来禁用缓冲