Python KeyboardInterrupt в многопоточности

Может ли кто-нибудь сказать мне, почему здесь не работает KeyboardInterrupt? Мне нужно завершить оба потока нажатием CTRL+C. Два потока — поток таймера и поток веб-сервера. Вот код -

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()       

person Vasudev Deshpande    schedule 01.05.2017    source источник
comment
Сначала исправьте отступ, чтобы код лучше читался.   -  person RPT    schedule 01.05.2017
comment
Сделанный. Надеюсь, сейчас лучше. Спасибо   -  person Vasudev Deshpande    schedule 01.05.2017
comment
Ваш отступ все еще отключен. Проверьте код внутри класса, особенно   -  person RPT    schedule 01.05.2017
comment
Я старался изо всех сил, приятель. Извините, если он все еще выключен.   -  person Vasudev Deshpande    schedule 01.05.2017


Ответы (2)


Во-первых, ваш экземпляр myThread, созданный с ошибкой, должен быть stopper=stopper (ожидается ключевое слово arg). Во-вторых, в коде есть ошибка, основной поток не ждет серверный поток, а сразу переходит к join()s. Итак, except никогда не бывает - ничего не будет напечатано. И основная ошибка в join(). Присоединение в Python не прерывается сигналами. Итак, вы должны написать собственную функцию соединения, которая будет вызывать исходный join() с тайм-аутом (например, 1 секунду), но в бесконечном цикле. Лучше сделать соединение с небольшим тайм-аутом, а затем - sleep() - сон можно прерывать. Оба в петле.

person RandomB    schedule 01.05.2017

Попробуйте напечатать что-то следующее из except KeyboardInterrupt, прежде чем вызывать join()s, соединения bcz ожидают завершения потоков.

person RandomB    schedule 01.05.2017
comment
Его не печатают. - person Vasudev Deshpande; 01.05.2017