J'ai un peu de code en cours d'exécution dans un thread d'attendre une connexion client entrant à l'aide d'une prise:boucle de terminaison avec le sélecteur de flux en Python 3
import threading
import socket
import selectors
class Server(threading.Thread):
def __init__(self):
# instantiate socket
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind the socket
self.socket.bind(("localhost", 50000))
def run(self):
# create selector to interface with OS
sel = selectors.DefaultSelector()
# register the connection handler for when a client connects
sel.register(self.socket, selectors.EVENT_READ, self.handle_connection)
while True:
events = sel.select()
for key, _ in events:
# run the callback
key.data()
def handle_connection(self):
# handle a request on the socket
data = self._socket.accept()
# do stuff with data...
def stop(self):
# what to do?
pass
Ce code entre dans la boucle while True
et appelle sel.select()
qui bloque jusqu'à ce que quelque chose soit lu de self._socket
, sur lequel il appelle le rappel self.handle_connection
(pas pertinent à ma question). Cela fonctionne bien, mais ce que je voudrais aussi pouvoir faire est de rompre la boucle while True
en utilisant la méthode stop
du thread, de sorte que ma boucle principale de programme ailleurs puisse arrêter le thread et éteindre le serveur gracieusement.
Je ne peux pas simplement vérifier un drapeau comme while self.running:
parce que sel.select()
bloque jusqu'à ce que quelque chose soit lu. J'ai également pensé à utiliser le mécanisme de gestion des erreurs du sélecteur, mais je ne veux pas nécessairement arrêter le serveur juste pendant les erreurs/exceptions.
Il semble que j'ai besoin du sélecteur pour lire à partir d'un deuxième flux qui contiendrait une commande spéciale pour arrêter la boucle, mais cela semble trop compliqué. Toute suggestion serait appréciée!
Le paramètre 'timeout' dans' select' vous aidera peut-être? https://docs.python.org/3.4/library/selectors.html#selectors.BaseSelector.select – Highstaker
Ah oui, c'est tout! J'ai ajouté un timeout de 1 seconde et changé la boucle 'while while' en' self.server_running', et fait la méthode 'stop' set' self.server_running = False'. Aussi simple que cela! Je vous remercie. – Sean
Pas de problème! Je posterai une réponse pour que d'autres personnes puissent l'utiliser, comme suggéré ici https://meta.stackexchange.com/questions/291167/posting-an-answer-after-posting-it-in-comment-that-solved- le problème-ops/291168 # 291168 – Highstaker