2015-04-12 10 views
6

Próbuję usunąć wszystkie znaki na linii po odzyskaniu z nieznanego stanu, ponieważ w niektórych przypadkach zawierają one podpowiedzi i inne słowa kluczowe, których używam w przyszłości oczekują wywołania metod. Próbowałem wielu podejść z mieszanym rezultatem, ponieważ ciągle mam nieoczekiwane zachowania.python pexpect wyczyszczenie lub przepłukanie linii

widziany nieoczekiwanych zachowań (używając pexpect v3.3 z Python 2.7.9):

  1. Po wykonaniu następującego kodu, kiedy następnie spróbować odczytać z bufora, czasami widzę nieprawidłowe działanie, gdzie tylko część nagromadzonych znaków została wyczyszczona. To budzi spustoszenie w mojej logice. Zakładam, że dzieje się tak, ponieważ cały wątek zostaje uśpiony na 5 sekund, więc gdy się budzi, nie ma czasu na pobranie pełnego bufora przychodzącego przed wykonaniem polecenia read_nonblocking().

    time.sleep(5) 
    flushedStuff += child.read_nonblocking(100000, timeout=0) 
    
  2. Kiedy próbuję użyć .expect wezwanie do spłukiwania linię w sposób non-blocking, okazało się, że po wyjątkiem TIMEOUT bufor przychodzące nie zostanie usunięty. Jego zawartość można znaleźć zgodnie z oczekiwaniami w właściwości child.before, ale będzie ona również analizowana podczas następnego wywołania metody .expect. To w ogóle nie powoduje opróżnienia linii! Zauważyłem także, że read_nonblocking() nie czyta z lokalnego bufora, ale czyta bezpośrednio z linii przez system operacyjny, więc tego nie widzi.

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

Więc po tym wszystkim, moje obecne rozwiązanie, aby zapewnić niezawodną drogę do spłukiwania linii jest rozszerzenie klasy odradzania i dodać metodę, który wykonuje następujące ... który uzyskuje dostęp do własności nieudokumentowane:

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 

Powyższa metoda może być również użyta do niezablokowania polecenia sleep.

To chyba zbyt skomplikowane podejście do czegoś, co powinno być proste, nie wspominając, że zmarnowałem na to kilka dni. Czy jest lepszy sposób na zrobienie tego?

Dzięki!

Odpowiedz

0

Najłatwiej usunąć pexpect buforować je odczytać w sposób ciągły aż do danych jest dostępny

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

widzi ten problem, można uruchomić następujący skrypt. (A skrypt wypisze numery od 1 do 10, a spać 1 sekundy po każdym numerze pexpect będzie czekać 2 sekundy dla timeout i drukować numery widoczne..):

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

Wyjście będzie wyglądać następująco (Otrzymujemy również numery już odczytane wcześniej):

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' 

rozwiązać problem dwa wiersze można dodać do skryptu:

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

a wyjście będzie zgodnie z oczekiwaniami:

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' 
Powiązane problemy