代码之家  ›  专栏  ›  技术社区  ›  user135361

SocketServer ThreadingMixIn用于server_thread

  •  5
  • user135361  · 技术社区  · 11 年前

    在异步(线程)SocketServer的示例中 http://docs.python.org/2/library/socketserver.html 启动服务器线程(称为serverthread),为每个请求启动新线程。由于捕获KeyboardInterrupts时遇到了一些问题,我开始寻找类似的代码,并发现不使用服务器线程时没有明显的区别,但ctrl-c确实有效。

    尽管我的代码有效,但我很想知道

    1) 在使用server_thread时,为什么不简单地“尝试”捕获KeyboardInterrupt?

    2) 这个示例中的server_thread有什么好处?

    在python SocketServer示例中,在try中捕获键盘中断不起作用:

    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 回复  |  直到 9 年前
        1
  •  5
  •   freakish    11 年前

    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) 它只是在单独的线程中启动服务器。也许你的想法是,你可以同时做其他手术?如果您只想运行服务器,则无需这样做。

    原因也可能是我上面说过的:优雅的退出。如果您只是中断服务器,它可能会在某些重要操作过程中死亡。

        2
  •  1
  •   User    11 年前

    在服务器线程示例中,您将启动一个新的线程来提供内容。 此线程不是作为deamon启动的( deamon = False ). 这意味着程序将在 server_forever() 完成。 因此,主线程不执行任何操作,程序等待非deamon线程关闭。

    1. 我看到的唯一区别是,这个新线程不是主线程,因此不处理KeyboardInterrupt或主线程所做的其他事情。
    2. 如果您想将GUI与服务器集成,这可能很有用。GUI可以并行运行。