在异步(线程)SocketServer http://docs.python.org/2/library/socketserver.html的示例中,启动服务器线程(称为server_thread),为每个请求启动新线程。由于捕获KeyboardInterrupts的一些问题,我开始寻找类似的代码,发现在不使用服务器线程时没有明显的区别,但ctrl-c实际上有效。
即使我的代码有效,我也非常想知道
1)为什么在使用server_thread时没有简单的'尝试'来捕获KeyboardInterrupt?
2)示例中的server_thread有什么用处 - 而不是我的一些简单的例子?
从python SocketServer示例中,在try中捕获keyboardinterrupt不起作用:
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()
答案 0 :(得分:4)
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)它只是在一个单独的线程中启动服务器。也许这个想法是你可以在此期间做其他操作?如果您只想运行服务器,则无需执行此操作。
也可能是我上面提到过的原因:优雅的戒烟。如果您只是中断服务器,它可能会在某些重要操作期间死亡。
答案 1 :(得分:1)
在服务器线程示例中,您将启动一个提供内容的新线程。
此线程不是作为deamon(deamon = False
)启动的。这意味着在server_forever()
完成之前程序不会退出。
所以主线程什么都不做,程序等待非deamon线程关闭。