python pexpect 清除或刷新行

标签 python pexpect

我试图在从未知状态恢复后清除行中的任何字符,因为在某些情况下它们包含提示和我在未来 expect 方法调用中使用的其他关键字。我尝试了多种方法,结果好坏参半,因为我不断遇到非预期的行为。

看到意外行为(将 pexpect V3.3 与 Python 2.7.9 结合使用):

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

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

    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

上述方法也可以用于非阻塞 sleep 命令。

对于本应简单的事情来说,这似乎是一种过于复杂的方法,更不用说我在这上面浪费了几天时间。有更好的方法吗?

谢谢!

最佳答案

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

关于python pexpect 清除或刷新行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29585522/

相关文章:

python - 启动语义图像识别

python-2.7 - pexpect.EOF : End Of File (EOF). 异常样式平台

python - 无法通过 python 记录器打印预期响应

python-2.7 - 如何设置 pexpect ssh session 的列宽?

登录失败时生成 Python PXSSH GUI

jQuery - 无法解析 json

python - 如何将 pandas 数据框行转换为逗号分隔的字符串

python - paramiko 如何在流中寻找直到模式匹配

python - 确定进程是否已成功终止

python - 使用 pdb 的条件断点