2011-12-21 10 views
5

Sto scrivendo un programma che visualizza il testo sul terminale usando Unix less (1). Ecco la parte pertinente:Input fallito dopo aver ucciso meno (1) sottoprocesso

In attesa di una conclusione inferiore, ascolto l'eccezione KeyboardInterrupt. Se ne prendo uno, uccido meno con un segnale SIGTERM e esco dal mio programma.

Ora, quando ciò accade, sono tornato al prompt della shell, ma la shell non riecheggia più ciò che scrivo e devo eseguire un reset (1) per farlo funzionare di nuovo.

Qualche idea su come rendere meno muoiono senza portare il mio stdin con esso nella tomba? La sorgente completo è disponibile sul https://github.com/jforberg/rfc/blob/master/rfc.py

EDIT: Dopo alcuni esperimenti, ho scoperto che sia meno (1) e l'uomo (1) di default ignorare la corsa di controllo-C. Quindi semplicemente ignorarlo potrebbe essere un'opzione praticabile. Non sono sicuro di pensare che sia il modo giusto di farlo, quindi se qualcuno ha dei suggerimenti sono ancora molto interessato.

+0

Come soluzione alternativa, potresti inserire un 'os.system ('reset')' alla fine del tuo script. La soluzione corretta probabilmente implicherà l'interruzione di 'less' educatamente, cioè scrivere un sigint e 'q' nel suo stdin e poi aspettare che si completi. – wim

+0

@wim re la tua "soluzione adeguata": certo! Il pensiero di scrivere la "q" a me stesso non mi era accaduto. Anche dopo un po 'di programmazione di Linux, devo ancora ricordare che tutto è un file. Per favore, trasferiscilo in una risposta e io lo accetterò. – jforberg

+2

Poiché non ci sono trucchi 'setpgid',' less' dovrebbe essere nello stesso gruppo di processi del processo Python, quindi riceverà lo stesso^C del processo Python.Suppongo che cerchi di fare il suo trattamento speciale, anche se ... Che ne dici di usare '-e' (' --quit-at-eof') in modo che possa uscire dopo che il tuo programma riaggancia? – ephemient

risposta

1

Il modo più semplice è quello di chiedere all'utente di uscire less correttamente (premendo q):

#!/usr/bin/env python 
from subprocess import PIPE, Popen 

p = Popen(['less'], stdin=PIPE) 
try: 
    p.communicate(''.join("%d\n" % i for i in range(1000))) 
except KeyboardInterrupt: 
    print("Press `q` to exit.") 
    p.wait() 
1

ci sono fondamentalmente due opzioni:

  1. Meno, programmi di uomo e affini non lo fanno terminano con il controllo C, interrompono qualsiasi operazione che stanno facendo al momento. Quindi semplicemente ignorare la sequenza di tasti sembra essere un'opzione. Ciò manterrebbe la caratteristica utile che le lunghe operazioni, come le ricerche lunghe, possono essere interrotte senza terminare il programma. È anche auspicabile che il programma funzioni come programmi simili (in questo caso, Unix man).

  2. Less accetta l'opzione -K che terminerà con control-C, proprio come la maggior parte dei comandi non interattivi.

0

Ah ah! La soluzione di J.F. Sebastian è buona, ma non funziona in tutti i casi. Nella mia applicazione voglio usare "less" come "tail -f" che è fatto con "less + F -S logfilename". L'utente deve premere CTRL + C per entrare in modalità normale, e loro Q per uscire.

Per questa procedura si verificano senza problemi, sono venuto con la seguente soluzione 6-linea (basato su J.F. codice Sebastian):

logpath = os.path.join(cwd, "filename.log") 
less = Popen(["less","+F","-S", logpath]) 
retcode = None 
while retcode is None: 
    try: retcode = less.wait() 
    except KeyboardInterrupt: pass 

Credo questo risolve l'originale. Se desideri inserire qualcosa in meno, potrebbe essere necessario modificare il metodo Popen utilizzato: wait() o communicate(input).

Problemi correlati