2012-11-01 10 views
46

Sto leggendo i dati seriali e scrivendo su un file csv usando un ciclo while. Voglio che l'utente sia in grado di uccidere il ciclo while una volta che ritengono di aver raccolto abbastanza dati.Come uccidere un ciclo while con un tasto?

while True: 
    #do a bunch of serial stuff 

    #if the user presses the 'esc' or 'return' key: 
     break 

ho fatto qualcosa di simile utilizzando OpenCV, ma non sembra funzionare in questa applicazione (e ho davvero non voglio importare OpenCV solo per questa funzione in ogni caso) ...

 # Listen for ESC or ENTER key 
     c = cv.WaitKey(7) % 0x100 
     if c == 27 or c == 10: 
      break 

Così. Come posso consentire all'utente di uscire dal ciclo?

Inoltre, non voglio usare l'interrupt di tastiera, perché lo script deve continuare a funzionare dopo che il ciclo while è terminato.

risposta

80

Il modo più semplice è interromperlo con il solito Ctrl-C (SIGINT).

try: 
    while True: 
     do_something() 
except KeyboardInterrupt: 
    pass 

Dal Ctrl-C cause KeyboardInterrupt di essere sollevato, basta prenderlo fuori del ciclo e lo ignorano.

+1

@Chris: perché non provarlo. (e poi commenta) – SilentGhost

+0

ho fatto subito dopo il commento ... ho dimenticato di cancellarlo. Ho contrassegnato questa risposta come accettata. – Chris

+0

Questo arresto anomalo (ottengo la traccia di errore) è '^ C' viene emesso mentre è in' do_something() '. Come puoi evitare questo? – Atcold

4

pyHook potrebbe aiutare. http://sourceforge.net/apps/mediawiki/pyhook/index.php?title=PyHook_Tutorial#tocpyHook%5FTutorial4

Vedere i ganci della tastiera; questo è più generalizzato-- se vuoi interazioni specifiche con la tastiera e non usare semplicemente KeyboardInterrupt.

Inoltre, in generale (a seconda dell'utilizzo) penso che avere l'opzione Ctrl-C ancora disponibile per uccidere il tuo script abbia senso.

leggi anche precedente domanda: Detect in python which keys are pressed

18

C'è una soluzione che non richiede moduli non standard ed è 100% trasportabile

import thread 

def input_thread(a_list): 
    raw_input() 
    a_list.append(True) 

def do_stuff(): 
    a_list = [] 
    thread.start_new_thread(input_thread, (a_list,)) 
    while not a_list: 
     stuff() 
+1

Solo una nota per coloro che usano Python 3+: raw_input() è stato rinominato in input() e il modulo thread ora è _thread. – Wieschie

+0

Non funziona in python 3, secondo Python 3: "I thread interagiscono stranamente con gli interrupt: l'eccezione KeyboardInterrupt viene ricevuta da un thread arbitrario. (Quando il modulo del segnale è disponibile, gli interrupt vanno sempre al thread principale). " – Towhid

+0

@Towhid Ma questo non utilizza interrupt. Usa la lettura da stdin. – Artyer

6

il seguente codice funziona per me. Richiede openCV (importazione cv2).

Il codice è composto da un loop infinito che cerca continuamente un tasto premuto. In questo caso, quando viene premuto il tasto 'q', il programma termina. È possibile premere altri tasti (in questo esempio 'b' o'k ') per eseguire azioni diverse, come cambiare un valore di variabile o eseguire una funzione.

import cv2 

while True: 
    k = cv2.waitKey(1) & 0xFF 
    # press 'q' to exit 
    if k == ord('q'): 
     break 
    elif k == ord('b'): 
     # change a variable/do something ... 
    elif k == ord('k'): 
     # change a variable/do something ... 
+2

Buono, ma cv2 è troppo pesante, a meno che non lo stiate già usando per qualcos'altro. – ogurets