Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python pexpect clearing or flushing the line

Tags:

python

pexpect

I am trying to clear any characters on the line after recovering from an unknown state, as in some cases they contain prompts and other keywords that I use in future expect method calls. I have tried multiple approaches with mixed results, as I keep running into non-expected behaviors.

Seen unexpected behaviors (using pexpect V3.3 with Python 2.7.9):

  1. After performing the following code, when I subsequently try to read from the buffer, occasionally I see erratic behavior where only part of the accumulated characters were cleared. This reeks havoc on my downstream logic. I assume that this is because the whole thread is put to sleep for 5 seconds, so when it wakes up it does not have time to fetch the full incoming buffer before executing the read_nonblocking() command.

    time.sleep(5)
    flushedStuff += child.read_nonblocking(100000, timeout=0)
    
  2. When I try to use an .expect call to flush the line in a non-blocking way, I found out that after a TIMEOUT exception the incoming buffer is not cleared. Its content can be found as expected in the child.before property, but it will also be parsed during the next .expect method call. So this does not flush the line at all! I also noticed that, read_nonblocking() does not read from the local buffer, but reads directly from the line through the OS, so it does not see this.

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

So after all this, my current solution to provide a reliable way to flush the line is to extend the spawn class and add a method that does the following ... which accesses an undocumented property:

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

The above method can also be used for a non-blocking sleep command.

This seems to be way too complex of an approach for something that should be simple, not to mention I wasted a couple of days on it. Is there a better way of doing this?

Thanks!

like image 422
user4061565 Avatar asked Apr 12 '15 03:04

user4061565


1 Answers

The easiest way to clear pexpect buffer is to read continuously till data is available

flushedStuff = ''
while not child.expect(r'.+', timeout=0.1):
    flushedStuff += child.match.group(0)
like image 154
Prem Anand Avatar answered Oct 04 '22 06:10

Prem Anand