Python 多线程中的键盘中断

Python KeyboardInterrupt in Multithreading

谁能告诉我为什么 KeyboardInterrupt 在这里不起作用?我需要按 CTRL+C 结束这两个线程。两个线程——定时器线程和Web 服务器线程。这是代码-

import threading
import thread
import time
import urllib2
import httplib

from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from SocketServer import ThreadingMixIn
import Queue
import signal
import sys

q = Queue.Queue()
j = Queue.Queue()
h = "threading working!"

class SignalHandler:
   stopper = None    
   def __init__(self,stopper):
      self.stopper = stopper

   def __call__(self, signum, frame):
      self.stopper.set()
      sys.exit(0)

#Timer Thread
class myThread(threading.Thread):
   stopper = None

   def __init__(self, **kwargs):
       self.req = []
       self.stopper = stopper
       for k, v in kwargs.iteritems():
           setattr(self, k, v)
       threading.Thread.__init__(self)

   def run(self):
       while not self.stopper.is_set():
           while self.go:
              try:
                 while True:
                     r = q.get_nowait()
                     self.req.append(r)
              except Queue.Empty, e:
                  pass
              t = threading.Timer(1,self.hello, [h])
              t.start()
              time.sleep(1)

   def hello(self, s):
      print s        
      while self.req:            
         r = self.req.pop()
         print "Client Request >>>>>>>", r                                            
         thread_id = str(threading.currentThread())
         j.put(thread_id)                                   

   def stop(self):
       print "Stopping thread.."
       self.go = False
       try:
           while True:
               q.get_nowait()
           q.task_done()
       except Queue.Empty, e:
           pass     

#Webserver thread
class Handler(BaseHTTPRequestHandler):

   def do_HEAD(self):
       self.send_response(200)        
       self.send_header("Content type", "text/html")
       self.end_headers()

   def do_GET(self):
       self.do_HEAD()
       req = (self.path, self.client_address, self.command,)        
       q.put(req)     
       self.wfile.write("Thread Info: ")
       self.wfile.write(j.get())                
       return        

class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
    """Handle requests in a separate thread."""

#main
if __name__ == '__main__':
   stopper = threading.Event()
   handler = SignalHandler(stopper)
   signal.signal(signal.SIGINT, handler)  
   server = ThreadedHTTPServer(('localhost', 8080), Handler)
   try:
       timer_thread = myThread(stopper,go=True)        
       timer_thread.start()    
       server_thread = threading.Thread(target=server.serve_forever)
       server_thread.daemon = True
       server_thread.start()        
       print 'Starting server, use <Ctrl-C> to stop'  
   except KeyboardInterrupt, e:
       print "Interrupted"
       q.join()
       j.join()
       timer_thread.stop()
       timer_thread.join()       

尝试打印 except KeyboardInterrupt 的下一个内容,然后再调用 join()s,bcz 连接正在等待线程完成。

首先,您的实例 myThread 创建时出错,必须是 stopper=stopper(需要关键字 arg)。第二,代码有错误,主线程没有等待服务器线程而是立即转到join()s。因此,except 永远不会发生 - 不会打印任何内容。主要错误在 join()。加入 Python 不会被信号中断。因此,您必须编写自己的连接函数,该函数将在无限循环中超时(例如,1 秒)调用原始 join()。更好的做法是让加入的超时时间很短,然后 - sleep() - 睡眠是可中断的。都在循环中。