2012-11-01 13 views
46

Czytam dane szeregowe i zapisuję do pliku csv za pomocą pętli while. Chcę, aby użytkownik mógł zabić pętlę while, gdy poczuje, że zebrał wystarczającą ilość danych.Jak zabić pętlę while za pomocą klawisza?

while True: 
    #do a bunch of serial stuff 

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

Zrobiłem coś takiego przy użyciu OpenCV, ale nie wydaje się działać w tej aplikacji (i naprawdę nie chcesz importować OpenCV tylko na tej funkcji tak) ...

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

So. Jak mogę pozwolić użytkownikowi wyjść z pętli?

Ponadto, nie chcę używać przerwania klawiatury, ponieważ skrypt musi nadal działać po zakończeniu pętli while.

Odpowiedz

80

Najprostszym sposobem jest po prostu przerwać go zwykłym Ctrl-C (SIGINT).

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

Od Ctrl-C przyczyny KeyboardInterrupt zostać podniesiony, po prostu złapać ją na zewnątrz pętli i zignorować.

+1

@ Chris: dlaczego nie spróbujesz. (a następnie komentarz) – SilentGhost

+0

zrobiłem zaraz po komentarzu ... zapomniałem go usunąć. Zaznaczam tę odpowiedź jako zaakceptowaną. – Chris

+0

To zawiesza się (otrzymuję komunikat o błędzie wstecz) jest '^ C' jest wydawane podczas' do_something() '. Jak możesz tego uniknąć? – Atcold

4

pyHook może pomóc. http://sourceforge.net/apps/mediawiki/pyhook/index.php?title=PyHook_Tutorial#tocpyHook%5FTutorial4

Zobacz haczyki na klawiaturę; to jest bardziej ogólne - jeśli chcesz mieć określone interakcje z klawiaturą, a nie tylko używać KeyboardInterrupt.

Również ogólnie (w zależności od zastosowania), myślę, że posiadanie opcji Ctrl-C nadal jest dostępne, aby zabić twój skrypt ma sens.

Zobacz także poprzednie pytanie: Detect in python which keys are pressed

18

istnieje rozwiązanie, które nie wymaga niestandardowych modułów i jest w 100% przenośne

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

Tylko uwaga dla osób używających Python 3+: raw_input() został przemianowany na input(), a moduł wątku jest teraz _thread. – Wieschie

+0

Nie działa w Pythonie 3, zgodnie z python 3 docs: "Wątki wchodzą w interakcje z dziwnymi przerwami: wyjątek KeyboardInterrupt zostanie odebrany przez dowolny wątek (gdy moduł sygnału jest dostępny, przerwania zawsze trafiają do głównego wątku). " – Towhid

+0

@ Towhid Ale to nie używa przerwań. Używa odczytu ze stdin. – Artyer

6

Następujący kod działa dla mnie. Wymaga openCV (import cv2).

Kod składa się z nieskończonej pętli, która ciągle szuka naciśniętego przycisku. W takim przypadku, po naciśnięciu klawisza "q" program się kończy. Można naciskać inne klawisze (w tym przykładzie "b" lub "k"), aby wykonać różne akcje, takie jak zmiana wartości zmiennej lub wykonanie funkcji.

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

Dobrze, ale cv2 jest zbyt ciężki, chyba że używasz go już do czegoś innego. – ogurets

Powiązane problemy