在Python中停止socketserver.ThreadingMixIn
我在用 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
的标志,并采取相应的行动。这还要求你的处理程序是非阻塞的,也就是说它不会卡住其他操作。