IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Problème sortie de Thread


Sujet :

Python

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2011
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2011
    Messages : 65
    Points : 65
    Points
    65
    Par défaut Problème sortie de Thread
    Bonjour à tous,

    J'essaie de faire un petit programme de chat via python.
    J'ai réussi à résoudre certains problèmes mais sur celui-ci, je sèche.
    J'ai essayé pleins de choses, mais en définitive, je m'aperçois que je pars surtout dans tous les sens sans aboutir à un résultat.

    Le problème est le suivant. Lorsque mon serveur envoie l'instruction "Quit" au client, celui-ci devrait quitter. Hors, pour une raison que je n'arrive pas à déterminer, je n'arrive pas à stopper mes threads. Dans la version ci-dessous. C'est la fonction "Send" qui pose problème.
    J'ai l'erreur suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Sortie de boucle envoi
    Traceback (most recent call last):
      File "C:\Users\Austin\OneDrive\Python\Projets\netcommand\client.py", line 96, in <module>
        SENDER.join()
      File "C:\Program Files\Python35\lib\threading.py", line 1054, in join
        self._wait_for_tstate_lock()
      File "C:\Program Files\Python35\lib\threading.py", line 1070, in _wait_for_tstate_lock
        elif lock.acquire(block, timeout):
    KeyboardInterrupt
    Pouvez-vous m'indiquer quelques pistes car je tourne en rond et fini par faire n'importe quoi?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    """Module client pour lancement de commande à distance"""
     
    #!/usr/bin/env python3
    # -*- coding : utf-8 -*-
     
    import socket
    import sys
    import threading
    import _thread
     
    class SendCommand(threading.Thread):
        """Envoyer un message/commande"""
        def __init__(self, connexion):
            threading.Thread.__init__(self)
            self.connexion = connexion
            self.exits = False
            nom = self.getName()
            print("thread d'envoi : "+nom)
     
        def input_timeout(self, prompt, timeout=0.001):
            """Stop le prompt régulièrement et vérifie si le flag d'arrêt du thread toujours vrai"""
            #print(prompt,)
            timer = threading.Timer(timeout, _thread.interrupt_main)
            message = None
            if not self.exits:
                try:
                    timer.start()
                    message = input(prompt)
                except KeyboardInterrupt:
                    pass
                timer.cancel()
                return message
     
        def run(self):
            """Fonction d'émission de message"""
            while not self.exits:
                command = self.input_timeout("---")
                if command != "":
                    self.connexion.send(command.encode("UTF-8"))
                else:
                    pass
            self.connexion.send("Déconnexion".encode("UTF-8"))
            print("Sortie de boucle envoi")
            RECEIVER.quit()
     
        def quit(self):
            """Active le flag pour quitter le thread"""
            self.exits = True
     
     
    class ReceiverMessage(threading.Thread):
        """Recevoir un message d'un client"""
        def __init__(self, connexion):
            threading.Thread.__init__(self)
            self.connexion = connexion
            self.exit = False
            nom = self.getName()
            print("thread de réception : "+nom)
     
        def run(self):
            """Fonction de reception de message"""
            while 1:
                message = self.connexion.recv(1024).decode("UTF-8")
                if message.upper() == "QUIT":
                    break
                elif message != "":
                    print("*"+message+"*")
            print("Sortie de boucle réception")
            SENDER.quit()
            print("fin sender")
     
        def quit(self):
            """Active le flag pour quitter le thread"""
            self.exit = True
     
     
    if __name__ == '__main__':
        HOST = '192.168.1.90'
        PORT = 7998
     
    CONNEXION = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     
    try:
        CONNEXION.connect((HOST, PORT))
    except socket.error:
        print('Connexion impossible')
        sys.exit()
     
    print('Connexion établie')
     
    SENDER = SendCommand(CONNEXION)
    RECEIVER = ReceiverMessage(CONNEXION)
    SENDER.start()
    RECEIVER.start()
    print("A")
    SENDER.join()
    RECEIVER.join()
    print("B")
    #SENDER.quit()
    # print("C")
     
    # print("D")
     
     
    CONNEXION.close()
     
    print('Fin de la connexion avec le serveur')
    Merci d'avance.
    Excellente fin d'année à vous et joyeuses fêtes.

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Citation Envoyé par austin57 Voir le message
    Pouvez-vous m'indiquer quelques pistes car je tourne en rond et fini par faire n'importe quoi?
    On ne sait pas à quel thread _thread.interrupt_main postera le est supposé postera le KeyboardInterrupt: çà dépend de la plateforme mais çà ne sera pas le thread que vous voulez interrompre.
    Comme vous travaillez sous Windows, vous pouvez essayer de fabriquer une fonction de lecture avec timeout en utilisant msvcrt.kbhit et msvcrt.getch.
    De plus, vous pourriez réduire vos threads à 2 (la réception et le main), çà vous simplifierait la vie.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2011
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2011
    Messages : 65
    Points : 65
    Points
    65
    Par défaut
    Merci Wiztricks pour votre réponse.

    En fait, je souhaite faire un code que je peux ensuite utiliser sur autre chose que windows. Du coup, la solution utilisant mscvrt est alléchante mais inadaptée.
    A l'inverse, j'ai vu des solutions utilisant le module select/readline mais ces modules ne semblent fonctionner que sur Linux.
    Après, il y a des modules comme pygame ou curses mais ça me parait très lourd juste pour ça.
    Le but étant simplement qu'à l'envoi d'une commande pour quitter, la fonction input() s'arrête pour quitter le thread proprement sans avoir besoin que l'utilisateur presse la touche "Entrée".

    Bref, quelque chose qui semble simple devient compliqué!
    Dans le pire des cas, je pourrai faire deux codes - un pour plateforme unix et un pour plate-forme windows. Mais avant d'en arriver là, je voudrais être sur qu'il n'y a pas d'autres moyens.

    Pour la réduction à 2 threads, comme c'est la première fois que j'utilise ce module, j'ai voulu faire quelques essais. Mais, je pense que vous avez raison, pour le moment, je vais réduire le nombre de thread jusqu'à avoir trouvé une solution cross-plateforme.

    Si quelqu'un à des modules à me conseiller pour trouver une solution, je suis preneur.

    A+

  4. #4
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Juste une idée.

    Je n'ai jamais programmé de "chat", mais j'ai déjà bricolé un peu les serveurs sous Python.

    "socket" est un module de "bas niveau". Dans les applications simples, le serveur doit attendre la fin du traitement de la requête précédente pour accepter la suivante. Pour faire mieux que ça, on est obligé d'ajouter un traitement de type thread, et ça complique sérieusement le code.

    Mais il y a une autre solution qui consiste à utiliser le module "socketserver" qui lui, a déjà des primitives lui permettant de fonctionner en multithreading ou multiprocessing! Ceci avec le protocole UDP ou TCP.

    J'avais fait deux petits tutos sur le sujet il y a longtemps pour TCP avec pour exemple un serveur de calcul d'expressions mathématiques (Python 2 => à convertir en Python 3): les voir comme sources d'inspiration:

    http://python.jpvweb.com/mesrecettes...rveur_tcp_base

    http://python.jpvweb.com/mesrecettes...eur_tcp_stream
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2011
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2011
    Messages : 65
    Points : 65
    Points
    65
    Par défaut
    Bonjour tyrtamos,

    Concernant mon problème d'input bloquant, je n'ai pas trouvé de solution suffisamment pertinente pour le moment et surtout à un niveau que j'arrive comprendre. Mais ce n'est pas très grave car pour ce que je veux faire (qui n'est pas vraiment un programme de chat), j'ai trouvé une autre méthode que d'utiliser Input. J'ai toutefois suivi les conseils de Wiztricks et simplifié à 2 threads mon programme...et ça fonctionne presque comme je veux.

    Concernant l'utilisation de socketserver, j'étais déjà tombé sur votre site ou je vais fureter régulièrement
    Je vais voir si je suis capable d'utiliser ce module à bon escient.

    Dans tous les cas, merci pour votre aide.

Discussions similaires

  1. Réponses: 1
    Dernier message: 08/08/2006, 15h39
  2. problème sur les threads et les sémaphores
    Par ramislebob dans le forum Windows
    Réponses: 1
    Dernier message: 29/06/2006, 11h52
  3. [C#] Problème sur un Thread
    Par bisounux dans le forum Windows Forms
    Réponses: 7
    Dernier message: 27/04/2006, 20h43
  4. Problème dans un thread
    Par BNS dans le forum MFC
    Réponses: 3
    Dernier message: 23/03/2006, 14h21
  5. Réponses: 5
    Dernier message: 10/05/2005, 10h22

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo