Partage
  • Partager sur Facebook
  • Partager sur Twitter

Threads et multiprocessing

    9 juillet 2013 à 11:36:42

    Bonjour a tous !

    Je suis etudiant et actuellement en stage, je dois cree en python un programme contenant 2 threads, un executant un code, l'autre examinant les entrees du clavier. Si on tape un "q" au clavier, le thread examinant les lettres doit stopper l'execution de l'autre thread. J'ai appris le langage Python seulement il y a une semaine, donc si cette question peux vous paraitre tres bete, desol par avance ;)

    Pour cela, j'ai ecrit le code suivant :

    import time,thread

    def block(string,sleeptime):

         var = raw_input("Enter something ")

         if var in "Qq":

               thread.interrupt_main()

               thread.exit()

    threadF=thread.start_new_thread(block,("Blabla",2))

    try :

         i=0

         while i<10 :

              time.sleep(0.5)

              print "i="+str(i)

              i+=1

    except KeyboardInterrupt:

              print "You stopped the execution"

    Le thread gerant l'execution du code est le main, le thread gerant les actions clavier est threadF. 

    Mon probleme est le suivant : lorsque j'appuie sur le clavier, le programme fonctionne correctement, le threadF est suppriöe a la fin de son execution. Cependant, lorsque je n'appuie sur aucun touche, et que le pere s'execute "normalement", le fils continue d'exister a la fin de l'execution du pere. Comment puis-je faire pour "detruire" le fils ? Car il n'y a pas de methode du type terminate() ou join() dans cette librairie

    PS : j'ai deja essaye d'utiliser les librairies multiprocessing et threading, mais celle-ci ne s'adaptent pas a mon probleme, car les threads ne fonctionnent pas en reel parallelisme.

    Merci de votre aide ;)

    • Partager sur Facebook
    • Partager sur Twitter
      9 juillet 2013 à 11:46:46

      Car il n'y a pas de methode du type terminate() ou join() dans cette librairie

      La doc doit sûrement mentir alors.

      PS : j'ai deja essaye d'utiliser les librairies multiprocessing et threading, mais celle-ci ne s'adaptent pas a mon probleme, car les threads ne fonctionnent pas en reel parallelisme.

      Ici non plus. Les modules threading et thread réfèrent exactement au même code en C, sauf que threading se situe à un plus haut niveau d'abstraction pour garantir la portabilité.

      Par contre si, le module multiprocessing crée vraiment des processus parallèles qui peuvent s'exécuter sur plusieurs cœurs à la fois. Cela dit, pour attendre un input clavier tu n'as pas du tout besoin de "vrai" parallélisme.

      Question tout bête pour être sûr que tu as bien compris ce que tu viens d'écrire : c'est quoi, selon toi, la différence entre un processus et un thread ?

      -
      Edité par nohar 9 juillet 2013 à 11:58:27

      • Partager sur Facebook
      • Partager sur Twitter
      Zeste de Savoir, le site qui en a dans le citron !
        9 juillet 2013 à 12:43:44

        Euuuh, ca te va si je te dis que pour moi y'en a pas ? ;)

        En fait ce que je voulais dire par "execution en parallele" c'est qu'avec la librairie thread j'ai au moins "l'impression" que mes deux codes s'executent en parallele.

        Alors qu'avec la bibliotheque threading et multiprocessing, mes codes s'executent l'un apres l'autre. Du coup, si je lance en premier le thread qui fait l'acquisition d'une eventuelle touche du clavier, il bloque l'autre thread, ou alors il n'est execute qu'apres l'autre thread...

        • Partager sur Facebook
        • Partager sur Twitter
          9 juillet 2013 à 12:53:52

          En fait en refaisant le point sur tout ce que j'ai dit, ecrit, et envisage pour mon programme, en fait il me faudrait 2 processus.

          Mais comme pour moi un thread et un porocessus c'est la meme chose, j'ai utilise les librairies de threads...

          • Partager sur Facebook
          • Partager sur Twitter
            9 juillet 2013 à 12:56:09

            HKev68 a écrit:

            Euuuh, ca te va si je te dis que pour moi y'en a pas ? ;)

            Et pourtant...

            Un processus est un fil d'exécution géré par l'OS : en général chaque script s'exécute dans son processus à lui et tu vas avoir typiquement une instance de Python par processus. Par contre un thread, c'est un fil d'exécution à l'intérieur d'un processus : tu peux avoir plusieurs threads par processus.

            Quand tu as plusieurs threads, la mémoire du processus est partagée entre tes threads, alors que plusieurs processus ont chacun leur mémoire indépendante (du coup pour les faire communiquer il faut ruser). Plusieurs processus peuvent s'exécuter en parallèle sur plusieurs cœurs.

            En Python (et comme dans tous les langages interprétés) il existe une contrainte qui fait que plusieurs threads ne peuvent pas s'exécuter sur plusieurs cœurs en parallèle : le Global Interpreter Lock. Ça signifie que tes threads vont simplement se partager un cœur pour s'exécuter, mais ça n'a aucune importance si tu cherches juste à paralléliser pour obtenir un comportement asynchrone comme ici (par opposition au parallélisme pour la recherche de performances, où là il peut arriver que ça pose problème).

            En fait ce que je voulais dire par "execution en parallele" c'est qu'avec la librairie thread j'ai au moins "l'impression" que mes deux codes s'executent en parallele.

            Alors qu'avec la bibliotheque threading et multiprocessing, mes codes s'executent l'un apres l'autre. Du coup, si je lance en premier le thread qui fait l'acquisition d'une eventuelle touche du clavier, il bloque l'autre thread, ou alors il n'est execute qu'apres l'autre thread...

            Montre ton code avec le module threading.

            • Partager sur Facebook
            • Partager sur Twitter
            Zeste de Savoir, le site qui en a dans le citron !
              9 juillet 2013 à 12:57:33

              Sinon, au niveau de l'algo et de l'execution de mon code,

              l'entree au clavier n'arrive pas a tous les coups.

              Mon chef m'a demande de coder ce programme pour debugger ces programmes python, c'est a dire que si il veut verifier l'etat de variables a un moment donner, en appuyant sur q il stoppe l'execution du code. Si tout se passe bien durant toute l'execution du code, il n'appuie sur aucune touche. Mon principale probleme est donc : comment arreter le threadF qui scrute le clavier, quand le main a fini son execution.

              • Partager sur Facebook
              • Partager sur Twitter
                9 juillet 2013 à 13:00:15

                À la rigueur il y a aussi le code de ce sujet qui peut t'intéresser. Suffit de le lancer en boucle dans ton threadF jusqu'à ce qu'il y ait un "q" ou que le thread ait reçu l'instruction de s'arrêter (en settant une variable à False ou autre).

                -
                Edité par nohar 9 juillet 2013 à 13:00:51

                • Partager sur Facebook
                • Partager sur Twitter
                Zeste de Savoir, le site qui en a dans le citron !
                  9 juillet 2013 à 13:05:29

                  import threading,os,time,sys

                  class Functions():

                  def blocking(self):

                       for i in range (0,50):

                            print "thread 1 i="+str(i)

                            i+=1

                            print "thread 1 finished"

                  def executing(self,i):

                        time.sleep(5)

                        while i<50:

                            print "thread 2 i="+str(i)

                            i+=1

                            print "thread 2 finished"

                  if __name__ == "__main__":

                           Funct=Functions()

                           thread2 = threading.Thread(target = Funct.executing(5))

                           thread = threading.Thread(target = Funct.blocking())

                           print 'Finished'

                  En ajoutant un sleep dans la fonction executing, je m'attend a ce que pendant ce thread dort, l'autre thread s'execute. Sauf que lorsque je lance l'execution, je dois attendre 5 sec avant que la fonction executing s'execute, puis blocking.

                  Dans ma tete, si un thread dort, l'autre s'execute, non ? ou alors c#est les processus qui fonctionnent comme ca ?

                  • Partager sur Facebook
                  • Partager sur Twitter
                    9 juillet 2013 à 13:20:23

                    Ok, merci.

                    J'ai essaye d'utiliser le code que tu m'as donne en lien. J'ai une erreur sur le :

                    read, _, _ = select([sys.stdin], [], [], 3)
                    select.error: (10038, 'An operation was attempted on something that is not a socket')

                    Dans la boite ou je suis, on travaille sur Spyder avec Python 2.7, sous Windows, peut etre que le probleme vient de la, as-tu une solution a me proposer ?

                    • Partager sur Facebook
                    • Partager sur Twitter
                      9 juillet 2013 à 13:42:31

                      Car il n'y a pas de methode du type terminate() ou join() dans cette librairie

                      "La doc doit sûrement mentir alors."

                      Ces m2thodes existent dans la librarie threading, mais pas dans thread ;)

                      • Partager sur Facebook
                      • Partager sur Twitter
                        9 juillet 2013 à 13:58:37

                        Sur ton code précédent, appelle explicitement les méthodes start() de tes threads pour voir ?

                        • Partager sur Facebook
                        • Partager sur Twitter
                        Zeste de Savoir, le site qui en a dans le citron !
                          9 juillet 2013 à 14:18:50

                          en fait, ca ne me change pas mon probleme...

                          je ne vois pas comment je peux faire, sans avoir 2 processus en parallele avec 1 qui scrute et 1 qui execute du code... 

                          • Partager sur Facebook
                          • Partager sur Twitter
                            9 juillet 2013 à 14:23:43

                            En fait, si on revient a mon code initial, qui marche quasiment, excepte le fait que le threadF reste orphelin apres la fin d'execution du pere dans le cas ou on appuie sur aucune touche, j'ai ca quand je l'execute :

                            import time

                            import thread

                            def block(string,sleeptime):

                              var = raw_input("Enter something ")

                              if var in "Qq":

                                thread.interrupt_main()

                                thread.exit()

                            threadF=thread.start_new_thread(block,("Blabla",2))

                            try :

                              i=0

                              while i<10 :

                                time.sleep(0.5)

                                print "i="+str(i)

                                i+=1

                              print "Finish"

                            except KeyboardInterrupt:

                              print "You stopped the execution"

                            >>runfile(r'C:\Python27\Scripts\project_threads_work.py', wdir=r'C:\Python27\Scripts')
                            Enter something i=0
                            i=1
                            i=2
                            i=3
                            i=4
                            i=5
                            i=6
                            i=7
                            i=8
                            i=9
                            Finish

                            >>

                            Et quand je relance, le threadF se supprime, comme si le main ne laissait pas le temps au "thread fils" de finir, avant de se finir. J'ai essaye en rajoutant des sleep, ca change rien.

                            • Partager sur Facebook
                            • Partager sur Twitter
                              9 juillet 2013 à 14:42:57

                              Non mais je viens de voir ton erreur :

                              thread2 = threading.Thread(target = Funct.executing(5))
                              thread = threading.Thread(target = Funct.blocking())
                              

                              Ce sont les fonctions que tu dois passer en argument, pas leur retour.

                              thread2 = threading.Thread(target = Funct.executing, args=(5,))
                              thread = threading.Thread(target = Funct.blocking)
                              
                              thread.start()
                              thread2.start()
                              
                              • Partager sur Facebook
                              • Partager sur Twitter
                              Zeste de Savoir, le site qui en a dans le citron !
                                9 juillet 2013 à 15:03:46

                                ok, du coup mes threads sont bien lances uniquement lorsque j'execute le start. Avant ils s'exxecutaient des la creation du thread.

                                Sinon, tu aurais fait comment pour faire mon "exercice" ?

                                PS : comme dis plus haut, le code que tu m'as mis plus haut en lien me renvoie une erreur ;)

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  9 juillet 2013 à 15:13:50

                                  en  fait, j'ai une idee sur la cause de mon probleme du threadF qui ne se supprime pas. le raw_input est bloquant, et du coup, tant que le threadF n'a pas recu de caractere au clavier, il ne s'arrete pas. Je pense que ton code que tu m'a donne en lien pßourrait me permettre de faire fonctionner mon programme, faut juse que tu m'explique ce que veux dire l'erreur que j'ai ;)

                                  sinon une autre solution serait (je ne sais pas si c'est possible en python) de creer un pipe, dans lequelle on met comme entree en ecriture le clavier et le main, et en lecture le threadF. Du coup, lorsqu'on ecrit au clavier pour quitter le programme, le threadF le lit, et lorque le main a fini son execution, en derniere ligne de code, on ecrit "q" depuis le main dans le pipe. Un peu complique mais qu'est ce que tu en pense ? 

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    9 juillet 2013 à 15:18:35

                                    Apparemment le code que j'ai collé en lien plus haut ne doit pas être compatible sous Windows, puisqu'il ne semble pas accepter que l'on fasse un select() sur autre chose qu'une socket. À la base c'était un moyen d'essayer de se passer des threads, mais ça ne semble fonctionner que sur tous les OS de la Terre sauf Windows.

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                    Zeste de Savoir, le site qui en a dans le citron !

                                    Threads et multiprocessing

                                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                    • Editeur
                                    • Markdown