python pexpect清除或冲洗线

use*_*565 9 python pexpect

我试图在从未知状态恢复后清除该行上的任何字符,因为在某些情况下,它们包含我在将来期望方法调用中使用的提示和其他关键字.我已经尝试了多种混合结果的方法,因为我一直在遇到非预期的行为.

看到意外的行为(使用pexpect V3.3和Python 2.7.9):

  1. 执行以下代码后,当我随后尝试从缓冲区读取时,偶尔会看到不稳定的行为,其中只有部分累积的字符被清除.这对我的下游逻辑造成了严重破坏.我假设这是因为整个线程被置于休眠状态5秒,因此当它被唤醒时,它没有时间在执行read_nonblocking()命令之前获取完整的传入缓冲区.

    time.sleep(5)
    flushedStuff += child.read_nonblocking(100000, timeout=0)
    
    Run Code Online (Sandbox Code Playgroud)
  2. 当我尝试使用.expect调用以非阻塞方式刷新行时,我发现在TIMEOUT异常之后,传入缓冲区未被清除.它的内容可以在child.before属性中按预期找到,但在下一个.expect方法调用期间也会被解析.所以这根本不冲洗线!我还注意到,read_nonblocking()不从本地缓冲区读取,而是直接通过操作系统从该行读取,因此它没有看到这一点.

    try:
        child.expect("ZzqQJjSh_Impossible_String", timeout = 5)
    except pexpect.TIMEOUT:
        pass
    flushedStuff = child.before
    
    Run Code Online (Sandbox Code Playgroud)

所以在这之后,我提供一种可靠的方法来刷新行的当前解决方案是扩展spawn类并添加一个执行以下操作的方法...它访问一个未记录的属性:

class ExtendedSpawn(pexpect.spawn):
    def flushBuffer(delay)
        try:
            # Greedily read in all the incoming characters
            self.expect("ZzqQJjSh_Impossible_String", timeout = delay)
        except pexpect.TIMEOUT:
            pass
        # Clear local input buffer inside the spawn Class
        self.buffer = self.string_type()
        return self.before
Run Code Online (Sandbox Code Playgroud)

上述方法也可用于非阻塞睡眠命令.

对于一些应该简单的方法来说,这似乎过于复杂,更不用说我浪费了几天.有没有更好的方法呢?

谢谢!

Pre*_*and 6

清除 pexpect 缓冲区的最简单方法是连续读取直到数据可用

flushedStuff = ''
while not child.expect(r'.+', timeout=0.1):
    flushedStuff += child.match.group(0)
Run Code Online (Sandbox Code Playgroud)


小智 5

要查看问题,您可以运行以下脚本。(shell 脚本将回显数字 1 到 10,并在每个数字后休眠 1 秒。pexpect 将等待 2 秒超时并打印看到的数字。):

#!/usr/bin/env python
import pexpect
child = pexpect.spawn('/bin/sh -c "i=0; while [ $i -lt 10 ]:; do echo $((i=i+1)); sleep 1; done"')
while True:
    i=child.expect ([pexpect.TIMEOUT, pexpect.EOF], timeout=2)
    if i==0:
        print "before=%s" % child.before
    else:
        break
Run Code Online (Sandbox Code Playgroud)

输出看起来像这样(我们也得到了之前已经读过的数字):

before='1\r\n2\r\n'
before='1\r\n2\r\n3\r\n4\r\n'
before='1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n'
before='1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n'
before='1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n10\r\n'
Run Code Online (Sandbox Code Playgroud)

为了解决这个问题,可以在脚本中添加两行:

#!/usr/bin/env python
import pexpect
child = pexpect.spawn('/bin/sh -c "i=0; while [ $i -lt 10 ]:; do echo $((i=i+1)); sleep 1; done"')
while True:
    i=child.expect ([pexpect.TIMEOUT, pexpect.EOF], timeout=2)
    if i==0:
        print "before=%s" % repr(child.before)
        if child.before:
            child.expect (r'.+')
    else:
        break
Run Code Online (Sandbox Code Playgroud)

输出将如预期的那样:

before='1\r\n2\r\n'
before='3\r\n4\r\n'
before='5\r\n6\r\n'
before='7\r\n8\r\n'
before='9\r\n10\r\n'
Run Code Online (Sandbox Code Playgroud)