2013-01-20 43 views
3

以下程序掛起終端,使其忽略Ctrl+C。這是非常煩人的,因爲每次線程掛起時我都必須重新啓動終端。正在等待事件的程序中捕獲鍵盤中斷

有什麼方法可以在等待事件時捕捉到KeyboardInterrupt

import threading 
def main(): 
    finished_event = threading.Event() 
    startThread(finished_event) 
    finished_event.wait()#I want to stop the program here 
    print('done!') 
def startThread(evt): 
    """Start a thread that will trigger evt when it is done""" 
    #evt.set() 
if __name__ == '__main__': 
    main() 

回答

1

更新:在當前的Python 3部finished_event.wait()作品我的Ubuntu的機器上(與Python 3.2開始)。您不需要指定timeout參數,使用Ctrl + C來中斷參數。你需要通過對CPython的2

timeout參數下面是一個完整的代碼示例:

#!/usr/bin/env python3 
import threading 

def f(event): 
    while True: 
     pass 
    # never reached, otherwise event.set() would be here 

event = threading.Event() 
threading.Thread(target=f, args=[event], daemon=True).start() 
try: 
    print('Press Ctrl+C to exit') 
    event.wait() 
except KeyboardInterrupt: 
    print('got Ctrl+C') 

有可能是bugs有關Ctrl+C。測試它是否適用於您的環境。


老輪詢答案:

你可以試着讓解釋器運行的主線程:

while not finished_event.wait(.1): # timeout in seconds 
    pass 

如果你只是想等到子線程完成:

while thread.is_alive(): 
    thread.join(.1) 
+2

這可以做到沒有輪詢? – Navin

+1

我不知道。它與投票有關嗎?爲什麼輪詢不好?你可以測試'time.sleep(large_timeout)'是否被'Ctrl + C'中斷。儘管它仍在輪詢,它可能會盡快對「Ctrl + C」做出反應。如果您需要對事件做出響應,那麼應該在'finished_event.set()'上作出反應的代碼應該放入另一個線程中。 – jfs

+1

那麼,即使我不需要響應,我也傾向於避免輪詢,但我想這是唯一的解決方案。 – Navin

3

如果你想避免輪詢,你可以使用代替finished_event.wait()signal模塊的pause()功能。 signal.pause()是一個阻塞函數,當進程接收到信號時會被解除阻塞。在這種情況下,當^ C被按下時,SIGINT信號解除該功能。請注意,根據文檔,該功能在Windows上不起作用。我已經在Linux上試過了,它對我很有用。

我在這個SO thread中遇到過這個解決方案。

+1

有點遲了,但是非常感謝你的答覆:) – Navin

+1

我認爲你可以編輯你的答案更簡單直接,但是你解決了我的問題,謝謝! –

+0

@Navin:它在Windows上工作嗎? – jfs

0

您還可以修補Event.wait()函數以下列方式:

def InterruptableEvent(): 
    e = threading.Event() 

    def patched_wait(): 
     while not e.is_set(): 
      e._wait(3) 

    e._wait = e.wait 
    e.wait = patched_wait 
    return e 


>>> event = InterruptableEvent() 
>>> try: 
...  event.wait() 
... except KeyboardInterrupt: 
...  print "Received KeyboardInterrupt" 
... 
^CReceived KeyboardInterrupt 

這工作,因爲等待()的超時參數養一個KeyboardInterrupt。

+0

啊,但這仍然像投票接受答案:( – Navin