为啥执行某些命令后 Pexpect 会间歇性挂起(未检测到 EOF)?

Posted

技术标签:

【中文标题】为啥执行某些命令后 Pexpect 会间歇性挂起(未检测到 EOF)?【英文标题】:Why is Pexpect intermittently hanging (not detecting EOF) after executing certain commands?为什么执行某些命令后 Pexpect 会间歇性挂起(未检测到 EOF)? 【发布时间】:2012-09-20 18:19:49 【问题描述】:

上下文:

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

我所做的只是启动和停止服务。我通过spawning 进程来做到这一点,然后在打印时输出每一行,如下所示:

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\n 一起添加到expected 数组中,并处理返回值以跳出循环,它仍然挂在同一个地方。

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

【问题讨论】:

当你不做任何与子进程交互的事情时,你为什么要使用pexpect?如果您只对输出感兴趣,来自 stdlib 的subprocess 就足够了。 这是一个简化的例子。在生产版本中,有对 expect 等的调用,但我提交的精简示例本身无法正常工作。 我无法使用此代码复制您的问题。我不确定代码是问题所在。也许您只是没有从 zend 服务器获得任何输出? 【参考方案1】:

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

【讨论】:

以上是关于为啥执行某些命令后 Pexpect 会间歇性挂起(未检测到 EOF)?的主要内容,如果未能解决你的问题,请参考以下文章

django manage.py runserver 在第二个请求后挂起(间歇性)

如何使用 Python pexpect 执行操作系统命令?

为啥删除大型 NTFS 卷上的文件夹后文件操作会挂起

自动化shell脚本except与python的pexpect模块

Python的Pexpect的简单使用

pexpect模块