多线程中的Python KeyboardInterrupt

时间:2017-05-01 14:54:01

标签: python multithreading web-services keyboard-events keyboardinterrupt

任何人都可以告诉我为什么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()       

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

首先,您创建的实例myThread有错误,必须为stopper=stopper(预期为关键字arg)。其次,代码有错误,主线程不等待服务器线程但立即转到join() s。所以,except永远不会发生 - 什么都不打印。主要错误在join()。加入Python不会被信号中断。因此,您必须编写自己的join函数,该函数将使用超时(例如,1秒)调用原始join(),但是在不定式循环中。更好的是在没有超时的情况下进行连接,然后下一步 - sleep() - 睡眠是可以中断的。两者都在循环中。