2011-06-01 19 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

信号只传递给一个线程。无论是第一个线程还是第一个可用线程,取决于操作系统。

你必须实现你自己的逻辑关闭其他线程,或使它们守护线程,所以他们不会阻止进程退出。