问题
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()
回答1:
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.
回答2:
Try to print something next of except KeyboardInterrupt
, before to call join()
s, bcz joins are waiting for threads to complete.
来源:https://stackoverflow.com/questions/43721150/python-keyboardinterrupt-in-multithreading