2012-11-01 42 views
46

Tôi đang đọc dữ liệu nối tiếp và ghi vào tệp csv bằng cách sử dụng vòng lặp while. Tôi muốn người dùng có thể giết vòng lặp while khi họ cảm thấy họ đã thu thập đủ dữ liệu.Làm thế nào để giết một vòng lặp trong khi với một tổ hợp phím?

while True: 
    #do a bunch of serial stuff 

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

Tôi đã làm một cái gì đó như thế này sử dụng opencv, nhưng nó dường như không có tác dụng trong ứng dụng này (và tôi thực sự không muốn nhập opencv chỉ dành riêng cho chức năng này anyway) ...

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

So. Làm thế nào tôi có thể để người dùng thoát khỏi vòng lặp?

Ngoài ra, tôi không muốn sử dụng ngắt bàn phím, vì tập lệnh cần tiếp tục chạy sau khi vòng lặp while bị chấm dứt.

Trả lời

80

Cách dễ nhất là chỉ làm gián đoạn nó với thông thường Ctrl-C (SIGINT).

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

Kể từ Ctrl-C nguyên nhân KeyboardInterrupt được nâng lên, chỉ cần bắt nó bên ngoài vòng lặp và bỏ qua nó.

+1

@Chris: tại sao bạn không dùng thử. (và sau đó bình luận) – SilentGhost

+0

tôi đã làm ngay sau khi bình luận ... quên xóa nó. Tôi đã đánh dấu câu trả lời này là đã được chấp nhận. – Chris

+0

Sự cố này (tôi nhận được lỗi theo dõi lại) là '^ C' được cấp trong khi trong' do_something() '. Làm thế nào bạn có thể tránh điều này? – Atcold

4

pyHook có thể hữu ích. http://sourceforge.net/apps/mediawiki/pyhook/index.php?title=PyHook_Tutorial#tocpyHook%5FTutorial4

Xem móc khóa bàn phím; điều này được tổng quát hơn - nếu bạn muốn các tương tác bàn phím cụ thể và không chỉ sử dụng KeyboardInterrupt.

Ngoài ra, nói chung (tùy thuộc vào việc bạn sử dụng) Tôi nghĩ rằng việc có tùy chọn Ctrl-C vẫn có sẵn để giết tập lệnh của bạn có ý nghĩa.

cũng Xem câu hỏi trước: Detect in python which keys are pressed

18

Có một giải pháp mà không cần module phi tiêu chuẩn và là 100% vận chuyển

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

Chỉ cần một lưu ý cho những người sử dụng Python 3+: raw_input() đã được đổi tên thành đầu vào() và mô-đun chủ đề bây giờ là _thread. – Wieschie

+0

Không hoạt động trong python 3, theo python 3 docs: "Chủ đề tương tác lạ với ngắt: ngoại lệ KeyboardInterrupt sẽ nhận được bởi một chuỗi tùy ý. (Khi mô-đun tín hiệu khả dụng, ngắt luôn đi tới chuỗi chính.) " – Towhid

+0

@Towhid Nhưng điều này không sử dụng ngắt. Nó sử dụng đọc từ stdin. – Artyer

6

đoạn mã sau làm việc cho tôi. Nó yêu cầu openCV (nhập khẩu cv2).

Mã này bao gồm một vòng lặp vô hạn liên tục tìm kiếm một phím được nhấn. Trong trường hợp này, khi nhấn phím 'q', chương trình sẽ kết thúc. Các phím khác có thể được nhấn (trong ví dụ này 'b' hoặc 'k') để thực hiện các hành động khác nhau như thay đổi giá trị biến hoặc thực hiện một hàm.

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

Tốt, nhưng cv2 quá nặng, trừ khi bạn đã sử dụng nó cho một thứ khác. – ogurets