在Python中停止socketserver.ThreadingMixIn

0 投票
1 回答
1295 浏览
提问于 2025-04-18 14:25

我在用 Python 3.4 扩展 socketserver.ThreadingMixIn,想要建立一个自己的多线程服务器,同时保留原来的回调函数,只是为了记录日志。启动和创建这个服务器非常简单,按照 Python 的文档,我遇到的问题是用 server.shutdown() 来关闭服务器时,它会卡住,无法退出。我需要一种方法来关闭这个服务器,而不是使用 ctrl-c,因为这还涉及到服务器的图形界面。

基本的服务器代码:

class ServerBasic(socketserver.ThreadingMixIn,socketserver.TCPServer):

logging.basicConfig(level=logging.DEBUG,format='%(name)s: %(message)s',)   

def __init__(self, log_name,server_address, handler_class=ThreadedRequestHandler):
    self.logger = logging.getLogger(log_name)
    self.logger.debug('__init__')
    socketserver.TCPServer.__init__(self, server_address, handler_class)
    return

def server_activate(self):
    self.logger.debug('server_activate')
    socketserver.TCPServer.server_activate(self)
    return

def serve_forever(self):
    self.logger.debug('waiting for request')
    self.logger.info('Handling requests, press <Ctrl-C> to quit')
    while True:
        self.handle_request()
    return

扩展的类代码:

class ManagerServer(PIRServerBasic):


def __init__(self, log_name, handler_class=T_ManagerRequestHandler):
    self.tup_socket = (ipAddress, WELCOME_PORT) # tuple of the address and port
    self.log_name = log_name
    return ServerBasic.__init__(self, log_name, self.tup_socket, handler_class=handler_class)

下面是如何创建和运行这个服务器的代码:

o_serverManager = ManagerServer('Manager_Server', T_ManagerRequestHandler) 
t_managerServer = threading.Thread(target=o_serverManager.serve_forever)
t_managerServer.daemon = True 
t_managerServer.start()

sleep(15)
o_serverManager.shutdown()

在执行关闭命令后,程序就卡住了。

1 个回答

3

在你重写的 serve_forever 方法中,你把处理关闭请求的条件给去掉了。原来的方法是这样的:

def serve_forever(self, poll_interval=0.5):
    """Handle one request at a time until shutdown.

    Polls for shutdown every poll_interval seconds. Ignores
    self.timeout. If you need to do periodic tasks, do them in
    another thread.
    """
    self.__is_shut_down.clear()
    try:
        while not self.__shutdown_request:
            r, w, e = _eintr_retry(select.select, [self], [], [],
                                   poll_interval)
            if self in r:
                self._handle_request_noblock()
    finally:
        self.__shutdown_request = False
        self.__is_shut_down.set()

你需要在你的重写版本中实现一个类似的系统,去检查一个叫 __shutdown_request 的标志,并采取相应的行动。这还要求你的处理程序是非阻塞的,也就是说它不会卡住其他操作。

撰写回答