Python 多线程中的键盘中断
Python KeyboardInterrupt in Multithreading
谁能告诉我为什么 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()
尝试打印 except KeyboardInterrupt
的下一个内容,然后再调用 join()
s,bcz 连接正在等待线程完成。
首先,您的实例 myThread
创建时出错,必须是 stopper=stopper
(需要关键字 arg)。第二,代码有错误,主线程没有等待服务器线程而是立即转到join()
s。因此,except
永远不会发生 - 不会打印任何内容。主要错误在 join()
。加入 Python 不会被信号中断。因此,您必须编写自己的连接函数,该函数将在无限循环中超时(例如,1 秒)调用原始 join()
。更好的做法是让加入的超时时间很短,然后 - sleep()
- 睡眠是可中断的。都在循环中。
谁能告诉我为什么 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()
尝试打印 except KeyboardInterrupt
的下一个内容,然后再调用 join()
s,bcz 连接正在等待线程完成。
首先,您的实例 myThread
创建时出错,必须是 stopper=stopper
(需要关键字 arg)。第二,代码有错误,主线程没有等待服务器线程而是立即转到join()
s。因此,except
永远不会发生 - 不会打印任何内容。主要错误在 join()
。加入 Python 不会被信号中断。因此,您必须编写自己的连接函数,该函数将在无限循环中超时(例如,1 秒)调用原始 join()
。更好的做法是让加入的超时时间很短,然后 - sleep()
- 睡眠是可中断的。都在循环中。