W Pythonie 2.7, nazywając shutdown() działa, ale tylko jeśli służą pomocą serve_forever, ponieważ wykorzystuje asynchroniczny wybrać i pętla odpytywania. Uruchomienie własnej pętli za pomocą handle_request() ironicznie wyklucza tę funkcjonalność, ponieważ implikuje nieme wywołanie blokujące.
Od SocketServer.py za BaseServer:
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()
Herezje część mojego kodu dla robią wyłączenie blokady z innego wątku, używając zdarzenie czekać na zakończenie:
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")
myślę możesz wywołać "self.serve_forever()" po "self.stopped = True" i unikać implementacji "create_dummy_request (self)". Dla mnie to zadziałało, ale może istnieć subtelność, której mi brakuje. –
Jeśli chodzi o źródła 'BaseServer.serve_forever()' w Pythonie 2.7, widzę, że ma już zaimplementowaną flagę, '__shutdown_request', plus' __is_shut_down' 'threading.Event' na górze. Tak więc rzeczywistą odpowiedzią, którą tu widzę, jest linia 'allow_reuse_address = True'. –