问题描述
有人可以告诉我为什么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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!