SocketServer ThreadingMixIn 中 server_thread 的作用
在一个异步(多线程)SocketServer的例子中,启动了一个服务器线程(叫做server_thread),这个线程会为每个请求启动新的线程。由于在捕捉键盘中断(KeyboardInterrupt)时遇到了一些问题,我开始寻找类似的代码,发现其实不使用服务器线程的时候,效果没有明显区别,但按下ctrl-c确实能正常工作。
虽然我的代码能正常运行,但我还是很想知道:
1) 为什么在使用server_thread的时候,简单的'尝试'去捕捉键盘中断却不管用?
2) 这个例子中的server_thread有什么好处,跟我那个简单的例子相比有什么不同?
在python的SocketServer例子中,尝试捕捉键盘中断是无效的:
if __name__ == "__main__":
server = ThreadedTCPServer(serverAddr, SomeCode)
<snip>
# Start a thread with the server -- that thread will then start one
# more thread for each request
server_thread = threading.Thread(target=server.serve_forever)
server_thread.start()
而在我简单的例子中,按ctrl-c是有效的。
if __name__ == "__main__":
server = ThreadedTCPServer(serverAddr, SomeCode)
try:
server.serve_forever()
print "ctrl-c to exit"
except KeyboardInterrupt:
print "interrupt received, exiting"
server.shutdown()
2 个回答
在这个服务器线程的例子中,你启动了一个新的线程来处理内容。这个线程不是以守护线程的方式启动的(deamon = False
)。这意味着程序不会退出,直到server_forever()
这个函数执行完毕。所以主线程什么都不做,程序在等待那些非守护线程结束。
- 我看到的唯一区别是,这个新线程不是主线程,因此它不会处理键盘中断(KeyboardInterrupt)或者主线程处理的其他事情。
- 如果你想把图形用户界面(GUI)和服务器结合起来,这样做会很有用。图形用户界面可以和服务器同时运行。
1) 这是一个普遍的问题。当你按下CTRL+C时,系统会向正在运行的程序发送一个信号。在这个程序中,主线程会接收到这个信号,如果没有正确处理,主线程就会被打断。但是,这个信号不会影响其他线程。而且,只要还有非守护线程在运行,Python是不会退出的(因为这样做不安全)。如果你知道自己在做什么,可以加上这个:
server_thread = threading.Thread(target=server.serve_forever)
server_thread.daemon = True
server_thread.start()
这样应该就可以正常工作了(假设你在server_thread.start()
之后做一些事情,比如等待——否则Python会直接退出,不会等守护线程)。不过要记住,这样可能会在一些重要操作中杀掉你的服务器。为了避免这种情况,你应该实现一种优雅的退出方式:
import signal
if __name__ == "__main__":
server = ThreadedTCPServer(serverAddr, SomeCode)
# some code
server_thread = threading.Thread(target=server.serve_forever)
server_thread.start()
# some code
try:
signal.pause() # wait for a signal, perhaps in a loop?
except:
server.shutdown() # graceful quit
2) 这段代码的作用是启动一个在单独线程中的服务器。也许这样做的想法是你可以在这段时间内进行其他操作?如果你只是想运行服务器,其实没有必要这样做。
另外,原因可能就是我上面提到的:优雅退出。如果你直接中断服务器,它可能会在一些重要操作中途就死掉。