程式扎記: [ Python 常見問題 ] python pexpect clearing or flushing the line

標籤

2016年3月6日 星期日

[ Python 常見問題 ] python pexpect clearing or flushing the line

Source From Here
Question
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.
  1. time.sleep(5)  
  2. 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.beforeproperty, 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.
  1. try:  
  2.     child.expect("ZzqQJjSh_Impossible_String", timeout = 5)  
  3. except pexpect.TIMEOUT:  
  4.     pass  
  5. 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:
  1. class ExtendedSpawn(pexpect.spawn):  
  2.     def flushBuffer(delay)  
  3.         try:  
  4.             # Greedily read in all the incoming characters  
  5.             self.expect("ZzqQJjSh_Impossible_String", timeout = delay)  
  6.         except pexpect.TIMEOUT:  
  7.             pass  
  8.         # Clear local input buffer inside the spawn Class  
  9.         self.buffer = self.string_type()  
  10.         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?

How-To
The easiest way to clear pexpect buffer it to read continuously till data is available:
  1. flushedStuff = ''  
  2. while not child.expect(r'.+', timeout=5):  
  3.     flushedStuff += child.match.group(0)  


沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!