如何在提示前监控 child 的输出?

How to monitor child's output before promt?

这是一个慢速应用程序的示例代码。 (想象一个Linux的开机)这是DUT,应该控制。

#linux.py

import time

print('Loading kernel ......')
time.sleep(0.5)
print('Loading foo  [  OK  ]')
time.sleep(0.5)
print('Loading bar  [  OK  ]')
time.sleep(0.5)
input('login> ')

我想通过 pexpect python 脚本进行控制,如下所示。

# controller.py

import pexpect
import sys

pybin = sys.executable

command = pybin + ' linux.py' 

p = pexpect.spawn(command)
p.expect('> ', timeout = 5)
print(p.before.decode(), end='')
print(p.match.group(0).decode())
p.sendline('')

没问题,但我无法在 boot-up 之前获得 "Linux.py's" 引导的控制台输出。我的意思是,在登录提示之前我没有得到反馈。想象一下,在 boot-up 期间出现错误。上面的脚本将因超时异常而失败。

我的目标

监视 child 进程并在等待提示时打印它的输出。怎么做到的?

解决方案 1

我根据 问题找到了一个简单的方法

# controller.py

import pexpect
import sys

pybin = sys.executable

command = pybin + ' linux.py' 

p = pexpect.spawn(command)
while True:
    # The return value is the index of the matched string
    i=p.expect(['> ', '\n'], timeout = 5)
    print(p.before.decode(), end='')
    print(p.match.group(0).decode(), end='')
    if i==0:
        break
print()
p.sendline('')

关键是要等待多个"expected string"。然后决定哪个是真正的提示,哪个是行尾。如果错误以换行符终止,则此解决方案有效。

解决方案 2

其他方法是使用小超时并打印前字符串的正确块:

# controller.py

import pexpect
import sys

pybin = sys.executable

command = pybin + ' linux.py' 

p = pexpect.spawn(command)
timeout_cnt = 0
print_idx = 0
while True:
    try:
        i=p.expect('> ', timeout = 1)
        # prompt has arrived
        break
    except pexpect.TIMEOUT:
        timeout_cnt += 1
        if timeout_cnt>30:
            # A real timeout has occured
            raise
    finally:        
        print(p.before.decode()[print_idx:], end='')
        print_idx = len(p.before.decode())
print(p.match.group(0).decode(), end='')
print()
p.sendline('')