2015-04-12 11 views
6

Sto tentando di cancellare tutti i caratteri sulla linea dopo il ripristino da uno stato sconosciuto, poiché in alcuni casi contengono prompt e altre parole chiave che uso in futuro prevedono chiamate di metodo. Ho provato più approcci con risultati misti, mentre continuo a imbattersi in comportamenti non previsti.python pexpect clearing o flushing the line

comportamenti imprevisti Visto (utilizzando V3.3 pexpect con Python 2.7.9):

  1. Dopo aver eseguito il codice seguente, quando in seguito cerco di leggere dal buffer, di tanto in tanto vedo un comportamento irregolare dove solo parte dei personaggi accumulati sono stati cancellati. Ciò crea scompiglio nella mia logica downstream. Presumo che ciò avvenga perché l'intero thread viene messo in sospensione per 5 secondi, quindi quando si riattiva non ha tempo di recuperare il buffer in arrivo prima di eseguire il comando read_nonblocking().

    time.sleep(5) 
    flushedStuff += child.read_nonblocking(100000, timeout=0) 
    
  2. Quando si tenta di utilizzare una chiamata .expect per lavare la linea in modo non bloccante, ho scoperto che dopo un'eccezione di timeout del buffer nell'ingresso non viene cancellato. Il suo contenuto può essere trovato come previsto nella proprietà child.before, ma verrà anche analizzato durante la successiva chiamata al metodo .expect. Quindi questo non svuota affatto la linea! Ho anche notato che read_nonblocking() non legge dal buffer locale, ma legge direttamente dalla linea attraverso il sistema operativo, quindi non lo vede.

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

Quindi, dopo tutto questo, la mia soluzione attuale per fornire un modo affidabile per lavare la linea è quella di estendere la classe uova e aggiungere un metodo che fa la seguente ... che accede una proprietà non documentata:

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 

Il metodo precedente può essere utilizzato anche per un comando di sospensione non bloccante.

Questo sembra essere troppo complesso di un approccio per qualcosa che dovrebbe essere semplice, per non parlare che ho sprecato un paio di giorni. C'è un modo migliore per farlo?

Grazie!

risposta

0

Il modo più semplice per cancellare pexpect tampone per leggere in modo continuo fino dati sono disponibili

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

Per vedere il problema, è possibile eseguire il seguente script. (Uno script shell eco i numeri da 1 a 10, e il sonno 1 secondo dopo ogni numero pexpect attenderà 2 secondi per un timeout e stampare i numeri visti..):

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

L'output sarà simile a questa (otteniamo anche i numeri già letto prima):

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' 

per risolvere il problema di due linee possono essere aggiunte allo script:

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

E l'uscita sarà come previsto:

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'