en Python 2.7, llamar a shutdown() funciona, pero sólo si usted está sirviendo a través de serve_forever, ya que utiliza asíncrono y seleccionar un bucle de sondeo. Ejecutar su propio bucle con handle_request() irónicamente excluye esta funcionalidad porque implica una llamada de bloqueo tonta.
De BaseServer de SocketServer.py:
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:
# XXX: Consider using another file descriptor or
# connecting to the socket to wake this up instead of
# polling. Polling reduces our responsiveness to a
# shutdown request and wastes cpu at all other times.
r, w, e = select.select([self], [], [], poll_interval)
if self in r:
self._handle_request_noblock()
finally:
self.__shutdown_request = False
self.__is_shut_down.set()
Aquí está parte de mi código para hacer un cierre de bloqueo desde otro hilo, usando un evento que esperar a la finalización:
class MockWebServerFixture(object):
def start_webserver(self):
"""
start the web server on a new thread
"""
self._webserver_died = threading.Event()
self._webserver_thread = threading.Thread(
target=self._run_webserver_thread)
self._webserver_thread.start()
def _run_webserver_thread(self):
self.webserver.serve_forever()
self._webserver_died.set()
def _kill_webserver(self):
if not self._webserver_thread:
return
self.webserver.shutdown()
# wait for thread to die for a bit, then give up raising an exception.
if not self._webserver_died.wait(5):
raise ValueError("couldn't kill webserver")
pienso puede llamar a "self.serve_forever()" después de "self.stopped = True" y evitar implementar "create_dummy_request (self)". Me ha funcionado hasta ahora, pero puede haber una sutileza que me falta. –
En cuanto a fuentes 'BaseServer.serve_forever()' en Python 2.7, veo que ya tiene implementado un indicador, '__shutdown_request', más' __is_shut_down' 'threading.Event' en la parte superior. Entonces, la respuesta real que veo aquí es la línea 'allow_reuse_address = True'. –