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 de boucle infinie


Sujet :

Python

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    82
    Détails du profil
    Informations personnelles :
    Âge : 58
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 82
    Points : 36
    Points
    36
    Par défaut Problème de boucle infinie
    Bonjour,

    python 2.6 / Win7 / Pyscripter

    Je souhaite faire tourner une boucle infinie dans mon application et récuperer des valeurs dans un fichier Txt. Je vous apporte une version edulcorer de mon code.
    L'ennui, c'est que mon application plante au bout d'un certain nombre de boucle.
    Au début, je pensais que cela pouvait provenir de ma fonction "EcrireDansFichier()". Mais non, car si je neutralise l'accès à cette fonction, j'observe le même phénomène. Curieusement, je n'ai aucun message d'erreur provenant de Pyscriter...
    Le plantage m'est indiqué par le gestionnaire des tâches... qui me dit que mon application ne répond plus
    Le nombre de boucle n'est pas constant, je ne comprends pas d'où ça peut provenir. A priori, j'ai pas l'impression d'avoir réinventer l'eau tiède avec mon code ^^
    Si quelqu'un à une explication à me fournir, je suis preneur.
    Merci pour vos réponses

    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
    #!/usr/bin/python
    # -*- coding: iso-8859-15 -*-
     
    import wx
     
    class Bonjour(wx.Frame):
        def __init__(self, titre):
            wx.Frame.__init__(self, None,-1, title = titre, size = (200, 100))
            conteneur = wx.Panel(self,-1, size = self.GetClientSize())
            etiquette = wx.StaticText(conteneur,-1, "Bonjour tout le monde !",
                                       style = wx.ALIGN_CENTRE)
            etiquette.CentreOnParent()
     
    class MonApp(wx.App):
        def OnInit(self):
            fen = Bonjour("Exemple 1")
            fen.Show(True)
            self.SetTopWindow(fen)
     
            Nbre_Partie = 0
            Game_en_cours = []
     
            while True: # Boucle infini
               Nbre_Partie = Nbre_Partie + 1
               Game_en_cours = Game(Nbre_Partie)
     
            return True
     
    ###---------------------------------------------------------------------------------------------
    def Game(Nbre_Partie):
    ###---------------------------------------------------------------------------------------------
     
        # Initialisation
        Partie_en_cours = []
     
        FichierDebugPartie = '/Fichier_Debug_Partie.txt'
     
    ##---------------à Supprimer après Debug -----------------------------------------------------------------------------------
        EcrireDansFichier(FichierDebugPartie, "\n\n---------------------------------------------------------------------------")
        EcrireDansFichier(FichierDebugPartie, "-----  Nbre_Partie :  " + str(Nbre_Partie) + " ---------------------------------------------------")
        EcrireDansFichier(FichierDebugPartie, "---------------------------------------------------------------------------")
    ##---------------à Supprimer après Debug -----------------------------------------------------------------------------------
     
        return Partie_en_cours[:]
     
     
    ###-------------------------------------------------------------------------
    def EcrireDansFichier(nomF1, ligne1):
        """     Ecrit "ligne" dans le Fichier "nomF" """
    ###-------------------------------------------------------------------------
        of1 = open(nomF1, 'a')
        of1.write(ligne1 + '\n')
        of1.close()
     
    app = MonApp()
    app.MainLoop()

  2. #2
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France

    Informations professionnelles :
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Points : 970
    Points
    970
    Par défaut
    bonjour,

    en mettant une boucle infinie dans ton code de cette façon, tu ne rends jamais la main à la boucle infinie chargée de générer les événements et les repaints dans ton interface graphique.

    tu peux soit t'affranchir de ta boucle infinie, soit si tu en as absolument besoin, la basculer dans un thread (dans ce cas pense à ajouter un time.sleep(petite valeur non nulle) pour que le thread rende correctement la main).

  3. #3
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonjour,

    Plutôt que time.sleep (bloquant) utilisez wx.CallLater pour répéter une fonction.

    @+

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    82
    Détails du profil
    Informations personnelles :
    Âge : 58
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 82
    Points : 36
    Points
    36
    Par défaut
    Merci pour vos réponses.
    J'ai cherché des renseignements sur les tread, voir un tuto pour le naïf que je suis... afin de comprendre de quoi on parle, là....
    J'avoue être un peu perdu... Pas un seul tuto parle de la même façon d'aborder les choses. Si vous avez une URL en français
    Pour résumer :
    Soit j'utilise un tread pour remplacer ma boucle ?!?
    Soit j'abandonne l'idée d'une boucle infinie ?!?

    Euhhh ... Et comment je fais moi ?!?


    arf... Pas trouvé wxCallLater non plus dans la Doc de wx

  5. #5
    Membre éprouvé

    Homme Profil pro
    Diverses et multiples
    Inscrit en
    Mai 2008
    Messages
    662
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Diverses et multiples

    Informations forums :
    Inscription : Mai 2008
    Messages : 662
    Points : 1 273
    Points
    1 273
    Par défaut
    Bon, alors, si tu connais pas les threads, et n’es pas motivé pour les apprendre, ne t’y lance pas –*c’est un sujet délicat à maîtriser, il faut s’accrocher un peu, au début…

    De toute façon, une boucle infinie, t’en as déjà une*: la main loop de wxApp*! Pourquoi ne pas, par exemple, utiliser l’évènement EVT_IDLE, en le “bindant” à un callback (qui fait une seule fois le contenu de ta boucle à chaque fois), direct dans ton objet app*? Comme ça, à chaque fois que la boucle principale se tourne les pouces, elle appelle ta fonction.

    Si tu veux une exécution plus régulière, utilise un timer (PyTimer par ex.).

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    82
    Détails du profil
    Informations personnelles :
    Âge : 58
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 82
    Points : 36
    Points
    36
    Par défaut
    Bon.... Ce n'est pas que je ne suis pas motivé pour me frotter aux Tread, c'est que je n'ai rien trouvé de facile à lire. Tous les tutos que j'ai trouvé avaient une manière différente d'aborder le problème.

    Mont29, Je n'ai pas compris grand chose à ce que tu dis...

    l'idée générale de mon application, c'est de travailler en continu pendant que ma machine est en marche.
    l'idée d'un tread semble prometteuse, pour ce que j'en ai compris. Cependant, je ne vois pas comment m'affranchir d'une boucle infinie dans le cas qui me préoccupe.
    j'ai compris que j'ai une boucle infinie principale : la main loop de wxApp
    Et que je lui impose une autre boucle infinie supplémentaire (Ligne 23) : while True: # Boucle infini
    d'où conflit...
    alors, comment utiliser un tread dans ma classe MonApp() ?
    mystère et boule de gomme

  7. #7
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bon,

    De toute manière et pour le moment pas de thread en Python (Comprendre GIL) donc lorsque vous utilisez un GUI pensez a utiliser l'existant.

    La méthode la plus propre est sans doute celle décrite par wiztricks ici mais cela demande une certaine maîtrise.

    La suivante c'est d'utiliser l'existant, soit wx.CallLater/CallAfter (Ce qui est fait dans la première méthode avec l'after de Tk).

    @+

    Ps: Je n'ai rien contre les threads

  8. #8
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 341
    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 341
    Points : 36 861
    Points
    36 861
    Par défaut
    Salut,

    [quote=PauseKawa;6082829]De toute manière et pour le moment pas de thread en Python (Comprendre GIL) donc lorsque vous utilisez un GUI pensez a utiliser l'existant.[/CODE]

    Hum, Python donne accès au mécanisme de threading "offert" par l'OS. GIL 'sérialise' leur exécution et ne permet pas "à priori" de "profiter" de tous les CPU équipant les PC - depuis 2004 -.

    La méthode la plus propre est sans doute celle décrite par wiztricks ici mais cela demande une certaine maîtrise.
    Ce truc date un peu. et n'est nécessaire que pour passer du GUI au thread lorsque le traitement va durer "assez" pour perturber les temps de réponse du GUI. Ce qui n'est "à priori" pas le cas lorsqu'on écrit quelques lignes dans un fichier.

    l'idée générale de mon application, c'est de travailler en continu pendant que ma machine est en marche.
    l'idée d'un tread semble prometteuse, pour ce que j'en ai compris. Cependant, je ne vois pas comment m'affranchir d'une boucle infinie dans le cas qui me préoccupe.
    Fastoche: boucle infinie = pas la main pendant que l'ordi boulotte dans son coin et "reboot" pour en sortir. Et comme ce n'est pas ce que vous voulez, vous êtes "affranchi".
    Ce que vous voulez c'est une tache répétitive: toutes les x secondes (x décimal), vous écrivez votre fichier... et l'ennui d'avoir un GUI qui ne vous permet pas d'attendre x secondes avec 'sleep' comme vous pourriez le faire en "mode console".

    Les wx.CallLater/CallAfter suggérés par PauseKawa sont justement les fonctions qui permettront de remplacer le sleep...

    Cordialement,
    - W

  9. #9
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonjour,

    Citation Envoyé par wiztricks Voir le message
    Citation Envoyé par PauseKawa Voir le message
    De toute manière et pour le moment pas de thread en Python (Comprendre GIL) donc lorsque vous utilisez un GUI pensez a utiliser l'existant.
    Hum, Python donne accès au mécanisme de threading "offert" par l'OS. GIL 'sérialise' leur exécution et ne permet pas "à priori" de "profiter" de tous les CPU équipant les PC - depuis 2004 -.
    Merci pour la précision wiztricks, ma phrase pouvait prêter à confusion.

  10. #10
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    82
    Détails du profil
    Informations personnelles :
    Âge : 58
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 82
    Points : 36
    Points
    36
    Par défaut
    Bonjour,
    Voilà où m'ont menées mes tribulations en matière de Tread
    J'ai essayé de me servir de vos conseils éclairés. Je fournie dans la foulée le fruit de mes cogitations, si cela peut peut être servir à quelqu'un ^^
    Ce n'est sans doute pas un modèle de codage, mais ça a le mérite de répondre à ma demande.

    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
     
    #!/usr/bin/python
    # -*- coding: iso-8859-15 -*-
     
    import wx
    import threading
    import time
     
    #classe qui défini notre thread
    class MyThread (threading.Thread):
    	#methode qui initialise la classe
    	def __init__ (self):
                     self.ouvert = True
                     self.Nbre_Partie = 0
     
                     threading.Thread.__init__(self)
     
    	#methode principale du thread
    	def run(self):
                 #ici on declare la fonction qui va etre executee par le thread.
                 while self.ouvert : # Boucle infini
                     # Initialisation
                     Partie_en_cours = []
                     self.Nbre_Partie = self.Nbre_Partie + 1
                     FichierDebugPartie = '/Fichier_Debug_Partie.txt'
     
    ##---------------à Supprimer après Debug -----------------------------------------------------------------------------------
                     EcrireDansFichier1(FichierDebugPartie, "\n\n---------------------------------------------------------------------------")
                     EcrireDansFichier1(FichierDebugPartie, "-----  Nbre_Partie :  " + str(self.Nbre_Partie) + " ---------------------------------------------------")
                     EcrireDansFichier1(FichierDebugPartie, "---------------------------------------------------------------------------")
    ##---------------à Supprimer après Debug -----------------------------------------------------------------------------------
     
    class Bonjour(wx.Frame):
        def __init__(self, titre):
            wx.Frame.__init__(self, None,-1, title = titre, size = (200, 100))
            conteneur = wx.Panel(self,-1, size = self.GetClientSize())
            etiquette = wx.StaticText(conteneur,-1, "Bonjour tout le monde !",
                                       style = wx.ALIGN_CENTRE)
            etiquette.CentreOnParent()
     
     
    class MonApp(wx.App):
        def OnInit(self):
     
            #creation de notre thread
            Game = MyThread()
            Game.start()
     
            fen = Bonjour("Exemple 1")
            fen.Show(True)
            self.SetTopWindow(fen)
     
            return True
     
    ###-------------------------------------------------------------------------
    def EcrireDansFichier1(nomF1, ligne1):
        """     Ecrit "ligne" dans le Fichier "nomF" """
    ###-------------------------------------------------------------------------
        of1 = open(nomF1, 'a')
        of1.write(ligne1 + '\n')
        of1.close()
     
    app = MonApp()
    app.MainLoop()
    Et donc, 2 petites questions...

    je n'ai pas très bien compris intérêt d'un time.sleep(), en tout cas, mon code fonctionne sans...

    De même, pour l'usage d'un wx.CallLater/CallAfter, je n'ai pas très bien compris l'utilisation d'une telle méthode et à quoi cela pourrait me servir .

    si quelqu'un peut m'apporter quelques éclaircissements, merci d'avance
    Et si cette même personne peut me le montrer dans mon code et me l'expliquer
    merci d'avance

  11. #11
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonjour,

    Un petit exemple sur votre code (sans doute nul, je ne pratique pas wx)
    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
    #!/usr/bin/python
    # -*- coding: iso-8859-15 -*-
    #
    #
    import wx
     
     
    class Bonjour(wx.Frame):
        def __init__(self, titre):
            wx.Frame.__init__(self, None,-1, title = titre, size = (200, 100))
            conteneur = wx.Panel(self,-1, size = self.GetClientSize())
            etiquette = wx.StaticText(conteneur,-1, "Bonjour tout le monde !",
                                       style = wx.ALIGN_CENTRE)
            etiquette.CentreOnParent()
     
     
    class MonApp(wx.App):
        def OnInit(self):
            fen = Bonjour("Exemple 1")
            fen.Show(True)
            self.SetTopWindow(fen)
            self.Nbre_Partie = 0
            self.Game_en_cours = []
            wx.CallAfter(self.mafonction)
            return True
     
        def mafonction(self):
            self.Nbre_Partie += 1
            self.Game_en_cours = Game(self.Nbre_Partie)
            wx.CallLater(60, self.mafonction)
     
    ###---------------------------------------------------------------------------------------------
    def Game(Nbre_Partie):
    ###---------------------------------------------------------------------------------------------
     
        # Initialisation
        Partie_en_cours = []
     
        FichierDebugPartie = 'Fichier_Debug_Partie.txt'
     
    ##---------------à Supprimer après Debug -----------------------------------------------------------------------------------
        EcrireDansFichier(FichierDebugPartie, "\n\n---------------------------------------------------------------------------")
        EcrireDansFichier(FichierDebugPartie, "-----  Nbre_Partie :  " + str(Nbre_Partie) + " ---------------------------------------------------")
        EcrireDansFichier(FichierDebugPartie, "---------------------------------------------------------------------------")
    ##---------------à Supprimer après Debug -----------------------------------------------------------------------------------
     
        return Partie_en_cours[:]
     
    ###-------------------------------------------------------------------------
    def EcrireDansFichier(nomF1, ligne1):
        """     Ecrit "ligne" dans le Fichier "nomF" """
    ###-------------------------------------------------------------------------
        with open(nomF1, 'a') as of1:
            of1.write(ligne1 + '\n')
     
    app = MonApp()
    app.MainLoop()
    A vrais dire l'idée c'est d'utiliser le timer du gestionnaire d’événement (mainloop) pour programmer l’exécution d'une fonction.
    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
    import wx
     
    class Frame(wx.Frame):
        def __init__(self):
            wx.Frame.__init__(self, None, title="wx test")
            self.counter = 0
            p = wx.Panel(self)
            self.st = wx.StaticText(p, -1, str(self.counter), (25,25))
            self.timer = wx.Timer(self)
            self.timer.Start(360)
            self.Bind(wx.EVT_TIMER, self.Cycle)
            self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
     
        def OnCloseWindow(self, evt):
            self.timer.Stop()
            del self.timer
            self.Destroy()
     
        def Cycle(self, evt):
            self.counter += 1
            self.st.SetLabel(str(self.counter))
     
    app = wx.App(False)
    frm = Frame()
    frm.Show()
    app.MainLoop()
    @+

    Edit : J'avais mélanger les codes...

  12. #12
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    82
    Détails du profil
    Informations personnelles :
    Âge : 58
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 82
    Points : 36
    Points
    36
    Par défaut
    Bonjour,
    Merci pour ces deux exemples.
    Je constate une énorme économie de code et une sacrée simplification ^^
    Cependant, après avoir testé les deux applications, je trouve que le code avec wx.CallLater beaucoup moins rapide. Même en jouant sur la variable "60".

  13. #13
    Membre éprouvé

    Homme Profil pro
    Diverses et multiples
    Inscrit en
    Mai 2008
    Messages
    662
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Diverses et multiples

    Informations forums :
    Inscription : Mai 2008
    Messages : 662
    Points : 1 273
    Points
    1 273
    Par défaut
    Oui, forcément, wxCallLater (ou sa version sleep() ) n’est pas adaptée si tu as des tâches lourdes à exécuter –*pour cela, pas de miracles, c’est threads (ou même processus, si tu veux bénéficier des procs multi-cores sous python ).

    La question est donc de savoir si exécuter une “boucle” toutes les quelques millisecondes te suffit, ou s’il t’en faut plusieurs milliers (ou plus) par seconde*!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème de Boucle infinie
    Par Tanin dans le forum Oracle
    Réponses: 2
    Dernier message: 16/07/2012, 15h52
  2. [XL-2003] Problème de boucle infinie
    Par SkyCorp dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 17/11/2011, 00h27
  3. Réponses: 6
    Dernier message: 15/11/2010, 09h47
  4. [Débutant]Problème de boucle infini
    Par Keldou dans le forum Octave
    Réponses: 1
    Dernier message: 21/04/2007, 17h20
  5. Problème de boucle infinie...
    Par anne-so dans le forum Langage
    Réponses: 1
    Dernier message: 25/04/2006, 14h10

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