2011-06-01 18 views
4

我無法捕捉到主線程中的INT信號,請告訴我如何解決這個問題。我希望睡眠方法可以被CTRL + C中斷,但它會一直等到計時器結束。Python睡眠函數不捕獲中斷信號

import pygtk 
pygtk.require('2.0') 

import gtk 
import time 
import urllib2 
import re 
import signal 
import sys 

import __main__ 

from time import ctime, strftime, localtime 
from threading import Thread 

myThread = None 

class MyThread(Thread): 

    def __init__(self, filename): 
     Thread.__init__(self) 
     self.filename = filename; 
     self.terminate = False 

    def StopProcess(self): 
     self.terminate = True 

    def run(self): 
     while self.terminate <> True: 
      time.sleep(5) 
      self.terminate = True 

def SignalHandler(signum, frame): 
    if (myThread <> None): 
     myThread.StopProcess() 
    sys.exit() 

if __name__ == "__main__": 

    signal.signal(signal.SIGINT, SignalHandler) 

    myThread = MyThread("aaa") 
    myThread.start() 
+0

標準行爲是捕獲SIGINT並將其轉換爲KeyboardInterrupt異常。我很好奇,如果有一個原因,只是陷入異常,而不是足夠的? – Keith 2011-06-02 02:01:35

回答

2

信不信由你,這會奏效。

from Queue import Queue, Empty 
def signal_safe_sleep(delay): 
    q = Queue() 
    try: q.get(True, delay) 
    except Empty: pass 

或者,您可以創建使用os.pipe()一些文件描述符,然後你signal_safe_sleep函數中對他們使用select.select()。兩種方法都將允許在signal_safe_sleep返回之前調用Python信號處理程序。

+0

相同,我只改變了你的代碼片段的time.sleep函數,腳本仍然不會對ctrl + c做出反應並等待5秒。 – Mejmo 2011-06-01 22:24:33

+1

沒錯,這隻會在你的主線程調用signal_safe_sleep時才起作用,因爲主線程是獲取^ C的主線程。在你的代碼中,當SIGTERM出現時,主解釋器線程已經在它的關閉例程中(連接所有非守護線程)。我不確定你的SignalHandler函數甚至在這種情況下被調用。 – wberry 2011-06-01 22:42:10

+0

是的,你是對的,主線程末尾的signal.pause()做到了。謝謝! – Mejmo 2011-06-02 07:20:30

3

信號只傳遞給一個線程。無論是第一個線程還是第一個可用線程,取決於操作系統。

你必須實現你自己的邏輯關閉其他線程,或使它們守護線程,所以他們不會阻止進程退出。