本文介绍了多线程中的Python KeyboardInterrupt的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人可以告诉我为什么KeyboardInterrupt在这里不起作用吗?我需要通过按CTRL + C来结束两个线程.这两个线程-计时器线程和Web服务器线程.这是代码-

Can anyone please tell me why the KeyboardInterrupt is not working here? I need to end both of the threads by the press of CTRL+C. The two threads - Timer thread and Web server thread. Here is the code -

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

推荐答案

首先,在错误创建的实例myThread中,必须为stopper=stopper(应使用关键字arg).其次,代码有错误,主线程不等待服务器线程,而是立即转到join().因此,except永远不会发生-将不会打印任何内容.而主要错误在join()中. Python中的Join不能被信号打断.因此,您必须编写自己的连接函数,该函数将在不定的循环中以超时(例如1秒)超时调用原始join().更好的方法是加入很少的超时,然后-sleep()-睡眠可中断.两者都在循环中.

First, your instance myThread in created with error, must be stopper=stopper (keyword arg is expected). Second, code has error, main thread does not wait server thread but immediately go to join()s. So, except never happens - nothing will be printed. And main bug is in join(). Join in Python is not interruptable by signals. So, you must write own join function, which will call original join() with timeout (for example, 1 second) but in the infinitive loop. Better is to make join with little timeout and next - sleep() - sleep is interruptable. Both in the loop.

这篇关于多线程中的Python KeyboardInterrupt的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 06:34