2015-04-12 7 views
6

Ich versuche, alle Zeichen in der Zeile nach der Wiederherstellung aus einem unbekannten Zustand zu löschen, da sie in einigen Fällen Eingabeaufforderungen und andere Schlüsselwörter enthalten, die ich in Zukunft erwarte Methodenaufrufe verwenden. Ich habe mehrere Ansätze mit gemischten Ergebnissen ausprobiert, da ich immer wieder auf nicht erwartete Verhaltensweisen stoße.python pexpect clearing oder flushing die Zeile

gesehen unerwartetes Verhalten (mit pexpect V3.3 mit Python 2.7.9):

  1. Nach dem folgenden Code durchführt, wenn ich später versuchen, aus dem Puffer zu lesen, gelegentlich ich erratisches Verhalten sehen, wo nur Ein Teil der akkumulierten Charaktere wurde gelöscht. Das stört meine nachgelagerte Logik. Ich nehme an, dass dies daran liegt, dass der gesamte Thread für 5 Sekunden in den Ruhezustand versetzt wird, so dass er beim Aufwachen keine Zeit hat, den vollständigen eingehenden Puffer vor dem Ausführen des Befehls read_nonblocking() abzurufen.

    time.sleep(5) 
    flushedStuff += child.read_nonblocking(100000, timeout=0) 
    
  2. Wenn ich versuche, einen .expect Anruf zu verwenden, um die Leitung in einer nicht blockierenden Art und Weise zu spülen, fand ich heraus, dass die eingehenden Puffer nicht gelöscht, nachdem eine TIMEOUT Ausnahme. Sein Inhalt kann wie erwartet in der child.before-Eigenschaft gefunden werden, wird aber auch beim nächsten .expect-Methodenaufruf analysiert. Das spült also die Linie überhaupt nicht! Ich habe auch bemerkt, dass read_nonblocking() nicht aus dem lokalen Puffer liest, sondern direkt aus der Zeile durch das Betriebssystem liest, so dass es das nicht sieht.

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

So nach all dies, meine aktuelle Lösung, die eine zuverlässige Art und Weise, um die Leitung zu spülen ist die Spawn-Klasse zu erweitern und ein Verfahren hinzufügen, funktioniert die folgende ..., die eine nicht dokumentierte Eigenschaft zugreift:

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 

Die obige Methode kann auch für einen nicht blockierenden Schlafbefehl verwendet werden.

Dies scheint viel zu komplex zu sein für etwas, das einfach sein sollte, ganz zu schweigen davon, dass ich ein paar Tage damit verschwendet habe. Gibt es einen besseren Weg, dies zu tun?

Danke!

Antwort

0

Der einfachste Weg pexpect es zu löschen Puffer kontinuierlich bis zu lesende Daten vorhanden ist

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

das Problem zu sehen, können Sie das folgende Skript ausführen. (A-Shell-Skript wird die Zahlen 1 bis 10 Echo und Ruhezustand 1 Sekunde nach jeder Zahl pexpect 2 Sekunden für einen Timeout warten und drucken die Zahlen gesehen..):

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

Der Ausgang wird wie folgt aussehen (wir bekommen auch die Zahlen bereits lesen, bevor):

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' 

zur Lösung des Problems zwei Zeilen an das Skript hinzugefügt werden können:

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

und der Ausgang wird wie erwartet:

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'