python pexpect清除或刷新lin

2024-06-28 19:36:50 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图在从未知状态恢复后清除行上的任何字符,因为在某些情况下,它们包含提示和其他关键字,我在以后的expect方法调用中使用这些关键字。我尝试了多种方法,但结果参差不齐,因为我总是遇到不可预期的行为。

出现意外行为(将pexpect V3.3与Python 2.7.9一起使用):

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

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

    try:
        child.expect("ZzqQJjSh_Impossible_String", timeout = 5)
    except pexpect.TIMEOUT:
        pass
    flushedStuff = child.before
    

所以在所有这些之后,我目前提供一个可靠的方法来刷新行的解决方案是扩展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

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

这似乎是一个太复杂的方法,应该是简单的事情,更不用说我浪费了几天的时间。有更好的办法吗?

谢谢!


Tags: 方法命令selfchildread状态timeout关键字
2条回答

要查看问题,可以运行以下脚本。(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

输出将如下所示(我们也会得到之前已经读过的数字):

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'

要解决此问题,可以在脚本中添加两行:

#!/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

产出将如预期的那样:

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'

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

flushedStuff = ''
while not child.expect(r'.+', timeout=5):
    flushedStuff += child.match.group(0)

相关问题 更多 >