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 :

Plantage aléatoire du programme [Python 3.X]


Sujet :

Python

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Février 2015
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Aude (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Février 2015
    Messages : 7
    Points : 8
    Points
    8
    Par défaut Plantage aléatoire du programme
    Bonjours à tous !
    Voilà, à vrai dire mon programme est plus ou moins terminé, il s'agit d'un "timer de cube", vous vous demanderez surement ce que c'est : il s'agit d'un chronomètre pour les gens comme moi qui font du speedcubing, c'est à dire qui s'amusent à résoudre le Rubik's cube le plus rapidement possible.

    Mais là n'est pas la question !

    Il se trouve que ce programme "plante" de manière pour moi, totalement aléatoire. Je pense que c'est du au "thread" mais je dis ça presque au pif, parce que c'est la première fois que ce genre de problème m'arrive. (et c'est aussi la première fois que j'utilise un thread)
    Donc je fais appel aux programmeurs confirmés qui traînent sur ce forum pour me donner leur avis vis à vis de ce petit désagrément qui ne m'a pas empêcher de le terminer pour autant mais qui peut s'avérer gênant.

    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
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
     
    from random import*
    from tkinter import*
    from time import time,sleep
    import threading
     
    #Crée un mélange aléatoire de x mouvements, sans mouvements inutiles
    def melange(x):
        global last_scramble
        liste = [["U","U'","U2","u","u'","u2"],["D","D'","D2","d","d'","d2"],["R","R'","R2","r","r'","r2"],["L","L'","L2","l","l'","l2"],["F","F'","F2","f","f'","f2"],["B","B'","B2","b","b'","b2"]]
        if x < 40:
            d = 3
        else :
            d = 6
        c = 20
        a = 15
        r = 0
        scramble=""
        while r<x:
            a=randrange(6)
            b=randrange(d)
            if a != c :
                if a == 0 or a == 2 or a == 4:
                    if c != a+1 :
                        r=r+1
                        move=liste[a][b]
                        scramble = scramble+" "+move
                        c = a
                else:
                    if c != a-1 :
                        r=r+1
                        move=liste[a][b]
                        scramble = scramble+" "+move
                        c = a
        texte.config(text=scramble)
        dernier_melange.config(text=last_scramble)
        last_scramble = "Dernier mélange : "+scramble
     
    #Boucle tant que flag == 1 pour modifier la variable du temps (chrono) et ajoute le temps à liste_temps une fois la boucle terminée
    def chrono():
        montemps=time()
        while flag == 1:
            y="%.3f" % (time()- montemps)
            nombre.set(y)
        liste_temps.append(y)
        listeur()
     
    #Crée une variable d'affichage à partir de la liste des temps et calcule l'ao totale
    def listeur():
        global liste
        liste = ""
        for n in range(len(liste_temps)):
            liste = liste+str(liste_temps[n])+" "
        temps.delete('0.0','end')
        temps.insert(0.0,liste)
     
        #Calcul de temps sans DNF
        laine = len(liste_temps)
        for n in range (len(liste_temps)):
            if liste_temps[n] == "DNF":
                laine = laine-1
        #ao totale, autres best ao, pire et meilleur
        ao_totale_texte = "0.000"
        if laine>0:
            ao_totale_texte = 0
            ao_totale_texte = float(averageur(len(liste_temps)))
            ao_totale.configure(text="ao "+str(len(liste_temps))+" : "+"%.3f" % ao_totale_texte)
     
            #Meilleur et pire temps
            meilleur,pire = extremum(0,len(liste_temps))
            best.configure(text="best : "+str(meilleur))
            worst.configure(text="worst : "+str(pire))
     
            #best ao 5, 12 et 100
            if laine>4:
                ao_5.configure(text="best ao 5 : "+str(averageur(5)))
            else : ao_5.configure(text="best ao 5 : 0.000")
            if laine>11:
                ao_12.configure(text="best ao 12 : "+str(averageur(12)))
            else : ao_12.configure(text="best ao 12 : 0.000")
            if laine>99:
                ao_100.configure(text="best ao 100 : "+str(averageur(100)))
            else : ao_100.configure(text="best ao 100 : 0.000")
        else:#réinitialisation si aucun temps (suite à une suppression ou DNF)
            ao_totale.configure(text="ao "+str(len(liste_temps))+" : "+ao_totale_texte)
            best.configure(text="best : 0.000")
            worst.configure(text="worst : 0.000")
     
    def averageur(x):
        minimum = 10000
        test = 0
        laine = len(liste_temps)
        for n in range(len(liste_temps)-(x-1)):
            meilleur,pire = extremum(n,n+x)
            elimines = meilleur+pire
            for m in range(x):
                o = n+m
                if liste_temps[o] != "DNF":
                    test = test+float(liste_temps[o])
                else: laine = laine-1
            test = test-elimines
            if x > 2:
                test = (test/(x-2))
            else : test = test/x
            if test < minimum:
                minimum = test
                test = 0
        return "%.3f"%minimum
     
    def extremum(a,b):
        best = 1000000
        worst = 0
        for n in range (a,b):
            test1 = float(liste_temps[n])
            test2 = float(liste_temps[n])
            if test1 < best:
                best = test1
            if test2 > worst:
                worst = test2
        return best,worst
     
    def inter_on(event):
        global flag,stop
        if flag == 0 and stop == 0 and event.keysym == "space":
            t = threading.Thread(target=chrono)
            flag = 1
            t.start()
            stop = 1
        else:
            stop = 0
     
    def inter_off(event):
        global flag
        if event.keysym == "F11":
            plein_ecran(1)
        elif event.keysym == "Escape":
            plein_ecran(0)
        if flag == 1:
            flag = 0
            melange(w)
     
    def change(x):
        global w,liste_temps
        w = x
        melange(w)
        liste_temps = []
        listeur()
        ao_totale.configure(text="ao totale : 0.000")
        dernier_melange.configure(text="")
     
    def effacer(x):
        if len(liste_temps)>0:
            liste_temps.remove(liste_temps[x])
            listeur()
     
    def plus_2():
        if len(liste_temps)>0:
            liste_temps[-1] = "%.3f" % (float(liste_temps[-1])+2)
            listeur()
     
    def DNF():
        if len(liste_temps)>0:
            liste_temps[-1] = "DNF"
            listeur()
     
    def plein_ecran(x):
        fen.attributes("-fullscreen", x)
        if x == 1:
            fenetre.entryconfigure(0,label="Quitter le plein écran    [Echap]", command=lambda:plein_ecran(0))
        elif x == 0:
            fenetre.entryconfigure(0,label="Plein écran    [F11]", command=lambda:plein_ecran(1))
     
    #Variables
    flag = 0
    w = 20
    liste_temps = []
    last_scramble=""
    stop = 0
    # ---------- Programme principal ----------
    fen = Tk()
    fen.bind("<KeyRelease>",inter_on)
    fen.bind("<Key>",inter_off)
    # ----- Widgets -----
    texte = Label(fen,text="Veuillez patienter",font="{Tahoma} 18")
    texte.pack(pady=5)
     
    dernier_melange = Label(fen,text=last_scramble,font="{Tahoma} 14")
    dernier_melange.pack(pady=5)
     
    nombre = StringVar()
    nombre.set("0.000")
    temp = Label(fen,textvariable=nombre,font="{Tahoma} 200").pack()
     
    stats = Frame(fen)
    stats.pack()
     
    frame = Frame(stats)
    frame.grid(row=0,column=0,pady=10, padx=10)
     
    temps = Text(frame,font="{Tahoma} 18",width=31,height=7,wrap=WORD)
    temps.grid(column=0, row=0)
     
    scrollbar = Scrollbar(frame,command=temps.yview)
    scrollbar.grid(column=1, row=0, sticky=S+N)
     
    averages = Frame(stats,borderwidth=2,relief=GROOVE)
    averages.grid(row=0,column=1,padx=10,pady=5)
     
    best = Label(averages,text="best : 0.000",font="{Tahoma} 18")
    best.pack(padx=10)
     
    worst = Label(averages,text="worst : 0.000",font="{Tahoma} 18")
    worst.pack(padx=10)
     
    ao_totale = Label(averages,text="ao : 0.000",font="{Tahoma} 18")
    ao_totale.pack(padx=10)
     
    ao_5 = Label(averages,text="best ao 5 : 0.000",font="{Tahoma} 18")
    ao_5.pack(padx=10)
     
    ao_12 = Label(averages,text="best ao 12 : 0.000",font="{Tahoma} 18")
    ao_12.pack(padx=10)
     
    ao_100 = Label(averages,text="best ao 100 : 0.000",font="{Tahoma} 18")
    ao_100.pack(padx=10)
    # ----- Menu -----
    Cube = Menu(fen)
     
    fenetre = Menu(Cube,tearoff=0)
    fenetre.add_command(label="Plein écran    [F11]", command=lambda:plein_ecran(1))
    fenetre.add_separator()
    fenetre.add_command(label="Quitter", command=fen.destroy,)
    Cube.add_cascade(label="Fenêtre", menu=fenetre)
     
    Cubes = Menu(Cube, tearoff=0)
    Cubes.add_command(label="2x2x2", command=lambda:change(10))
    Cubes.add_command(label="3x3x3", command=lambda:change(20))
    Cubes.add_command(label="4x4x4", command=lambda:change(40))
    Cube.add_cascade(label="Catégorie", menu=Cubes)
     
    effacage = Menu(Cube, tearoff=0)
    effacage.add_command(label="Dernier temps", command=lambda:effacer(-1))
    effacage.add_command(label="Premier temps", command=lambda:effacer(0))
    Cube.add_cascade(label="Effacer", menu=effacage)
     
    penalite = Menu(Cube, tearoff=0)
    penalite.add_command(label="+2", command=plus_2)
    penalite.add_command(label="DNF", command=DNF)
    Cube.add_cascade(label="Pénalités", menu=penalite)
     
    fen.config(menu=Cube)
     
    melange(20)
    fen.mainloop()
    Voilà, et je dis un grand "merci !" d'avance à ceux qui essaieront de m'aider !
    (je tiens à préciser que je code depuis moins d'un an, j'ai commencé septembre dernier avec l'option ISN de mon lycée, je ne suis donc pas très expérimenté ^^')
    EDIT : au cas où, le thread est défini à la ligne 125 ^^

  2. #2
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 687
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 687
    Points : 30 980
    Points
    30 980
    Billets dans le blog
    1
    Par défaut
    Bonjour

    J'ai testé ce code chez-moi (Python 2.9) et ça n'a pas planté (ceci dit, ça n'a pas affiché grand-chose non plus mis à part un "0.000" immense et un menu sans effet hormis le plein-écran et quitter).

    Donc peut-être que tu devrais nous en dire plus sur ton plantage. Comment vois-tu qu'il y a plantage ? Est-ce que ta fenêtre disparait ? As-tu une stack-trace (ta fenêtre console affiche la ligne en erreur puis tout l'empilement des différents appels qui ont amené à exécuter la ligne en question mais ça implique bien évidemment que tu exécutes ton script depuis une fenêtre MsDos pour pouvoir afficher ladite stack).

    Maintenant quelques remarques générales sur ton code: tu devrais utiliser des noms de variables plus appropriés que a, c, d, r. Expliquer pourquoi d vaut 3 ou 6 en lignes 14 et 16. Et quand tu as un flag qui ne peut valoir que 0 ou 1 ben tu peux alors lui affecter False et True (et t'as même aussi la possibilté "None" pour les cas très particuliers). Et le if a == 0 or a == 2 or a == 4 s'écrira plus simplement if a in (0, 2, 4) ce qui permet de faire évoluer ce genre de test plus facilement. D'ailleurs, dans ce bloc, il y a 2 fois le même groupe d'instructions ce qui, grace à certaines astuces "spécial Python", est toujours évitable. Exemple

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    import operator
    op=operator.add if a in (2, 4, 6) else operator.sub
    if c != op(a, 1):
        r=r+1
        move=liste[a][b]
        scramble = scramble+" "+move
        c = a
    # if

    Ceci dit, pour un code de débutant tu t'es bien débrouillé

    PS: ça existe encore le rubik's ??? Je pensais cet amusement disparu dans l'évolution technologique. Ou alors c'est maintenant un rubik's 4D hypercube holographique avec écran plasma..
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Février 2015
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Aude (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Février 2015
    Messages : 7
    Points : 8
    Points
    8
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Bonjour

    J'ai testé ce code chez-moi (Python 2.9) et ça n'a pas planté (ceci dit, ça n'a pas affiché grand-chose non plus mis à part un "0.000" immense et un menu sans effet hormis le plein-écran et quitter).
    Effectivement ! je suis désolé j'ai oublié de dire comment on s'en sert :
    Tout simplement on appuie sur la touche d'espace pour lancer le chrono et sur n'importe quelle autre touche sauf "F11" ou "Echap" pour l'arrêter, celles-ci permettant d'accéder au mode plein écran et d'en sortir.

    Et oui le plantage se produit lorsque je fais plusieurs temps, surtout quand ceux-ci sont courts (moins d'une seconde), c'est carrément python qui plante avec le message de Windows "ne réponds pas"

    Nom : plantage python.jpg
Affichages : 392
Taille : 83,1 Ko

    Pour réaliser cette capture, bizarrement, j'ai du faire pas mal de temps avant que ça plante, parce qu'évidemment, quand on veut montrer le problème, celui-ci n'arrive pas !

    Et merci beaucoup pour les autres conseils, je me souviens m'être demandé justement comment on fait pour écrire plusieurs correspondances à une même variable dans une condition, mais j'avais vite abandonné après quelques essais au hasard ^^'

    Et "d" correspond à la variable du maximum que prendra mon second aléa, celui qui ira piaucher dans les listes dans la grande liste. C'est pas très clair comme ça mais je modifierai la variable dans un prochain post ainsi que mes conditions

    En tout cas merci beaucoup de ces conseils !

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

    Citation Envoyé par Pixelon Voir le message
    Il se trouve que ce programme "plante" de manière pour moi, totalement aléatoire. Je pense que c'est du au "thread" mais je dis ça presque au pif, parce que c'est la première fois que ce genre de problème m'arrive. (et c'est aussi la première fois que j'utilise un thread)
    Vous effectuez des mises à jour du GUI directement depuis le thread.
    Cette technique a le mauvais goût de fonctionner (pire, c'est techniquement supporté et construit pour) sans crier gare. Hélas, il faut éviter de le faire pour ne pas se retrouver avec des plantages bizarres comme ceux que vous constatez.

    Vous n'êtes pas le premier à tomber dans ce piège.
    Vous trouverez dans ce post récent les deux techniques à utiliser pour que votre code soit plus "robuste".

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

  5. #5
    Futur Membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Février 2015
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Aude (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Février 2015
    Messages : 7
    Points : 8
    Points
    8
    Par défaut
    Tout d'abord, merci de ta réponse wiztricks,
    je me suis penché sur le lien et j'ai effectué des modifications dans mon programme mais je crois que le problème est aggravé
    Je crois ne pas avoir bien saisi comment régler mon problème :/
    Tout d'abord, est-ce qu'il s'agit bien de la fonction parent.after_idle() ?
    Je reposte le code car j'ai modifié également selon les conseils de Sve@r sauf pour l'astuce avec le module "operator" qui est un peu plus complexe ^^' mais je le ferai plus tard promis (si j'arrive à comprendre toute fois)

    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
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    from random import*
    from tkinter import*
    from time import time,sleep
    import threading
     
    #Crée un mélange aléatoire de x mouvements, sans mouvements inutiles
    def melange(x):
        global last_scramble
        liste = [["U","U'","U2","u","u'","u2"],["D","D'","D2","d","d'","d2"],["R","R'","R2","r","r'","r2"],["L","L'","L2","l","l'","l2"],["F","F'","F2","f","f'","f2"],["B","B'","B2","b","b'","b2"]]
        if x < 40:
            variete_des_mouvements = 3
        else :
            variete_des_mouvements = 6
        precedent_mouvement = 20
        actuel_mouvement = 15
        n = 0
        scramble=""
        while n<x:
            actuel_mouvement=randrange(6)
            particularite=randrange(variete_des_mouvements)
            if actuel_mouvement != precedent_mouvement :
                if actuel_mouvement in (0,2,4):
                    if precedent_mouvement != actuel_mouvement+1 :
                        n=n+1
                        move=liste[actuel_mouvement][particularite]
                        scramble = scramble+" "+move
                        precedent_mouvement = actuel_mouvement
                else:
                    if precedent_mouvement != actuel_mouvement-1 :
                        n=n+1
                        move=liste[actuel_mouvement][particularite]
                        scramble = scramble+" "+move
                        precedent_mouvement = actuel_mouvement
        texte.config(text=scramble)
        dernier_melange.config(text=last_scramble)
        last_scramble = "Dernier mélange : "+scramble
     
    #Boucle tant que flag == True pour modifier la variable du temps (chrono) et ajoute le temps à liste_temps une fois la boucle terminée
    def chrono():
        montemps=time()
        while flag == True:
            y="%.3f" % (time()- montemps)
            fen.after_idle(lambda: nombre.set(y))
            sleep(0.0005)
        liste_temps.append(y)
        listeur()
     
    #Crée une variable d'affichage à partir de la liste des temps et calcule l'ao totale
    def listeur():
        global liste
        liste = ""
        for n in range(len(liste_temps)):
            liste = liste+str(liste_temps[n])+" "
        temps.delete('0.0','end')
        temps.insert(0.0,liste)
     
        #Calcul de temps sans DNF
        laine = len(liste_temps)
        for n in range (len(liste_temps)):
            if liste_temps[n] == "DNF":
                laine = laine-1
        #ao totale, autres best ao, pire et meilleur
        ao_totale_texte = "0.000"
        if laine>0:
            ao_totale_texte = 0
            ao_totale_texte = float(averageur(len(liste_temps)))
            ao_totale.configure(text="ao "+str(len(liste_temps))+" : "+"%.3f" % ao_totale_texte)
     
            #Meilleur et pire temps
            meilleur,pire = extremum(0,len(liste_temps))
            best.configure(text="best : "+str(meilleur))
            worst.configure(text="worst : "+str(pire))
     
            #best ao 5, 12 et 100
            if laine>4:
                ao_5.configure(text="best ao 5 : "+str(averageur(5)))
            else : ao_5.configure(text="best ao 5 : 0.000")
            if laine>11:
                ao_12.configure(text="best ao 12 : "+str(averageur(12)))
            else : ao_12.configure(text="best ao 12 : 0.000")
            if laine>99:
                ao_100.configure(text="best ao 100 : "+str(averageur(100)))
            else : ao_100.configure(text="best ao 100 : 0.000")
        else:#réinitialisation si aucun temps (suite à une suppression ou DNF)
            ao_totale.configure(text="ao "+str(len(liste_temps))+" : "+ao_totale_texte)
            best.configure(text="best : 0.000")
            worst.configure(text="worst : 0.000")
     
    def averageur(x):
        minimum = 10000
        test = 0
        laine = len(liste_temps)
        for n in range(len(liste_temps)-(x-1)):
            meilleur,pire = extremum(n,n+x)
            elimines = meilleur+pire
            for m in range(x):
                o = n+m
                if liste_temps[o] != "DNF":
                    test = test+float(liste_temps[o])
                else: laine = laine-1
            test = test-elimines
            if x > 2:
                test = (test/(x-2))
            else : test = test/x
            if test < minimum:
                minimum = test
                test = 0
        return "%.3f"%minimum
     
    def extremum(a,b):
        best = 1000000
        worst = 0
        for n in range (a,b):
            test1 = float(liste_temps[n])
            test2 = float(liste_temps[n])
            if test1 < best:
                best = test1
            if test2 > worst:
                worst = test2
        return best,worst
     
    def inter_on(event):
        global flag,stop
        if flag == False and stop == False and event.keysym == "space":
            t = threading.Thread(target=chrono)
            flag = True
            t.start()
            stop = True
        else:
            stop = False
     
    def inter_off(event):
        global flag
        if event.keysym == "F11":
            plein_ecran(1)
        elif event.keysym == "Escape":
            plein_ecran(0)
        if flag == True:
            flag = False
            melange(w)
     
    def change(x):
        global w,liste_temps
        w = x
        melange(w)
        liste_temps = []
        listeur()
        ao_totale.configure(text="ao totale : 0.000")
        dernier_melange.configure(text="")
     
    def effacer(x):
        if len(liste_temps)>0:
            liste_temps.remove(liste_temps[x])
            listeur()
     
    def plus_2():
        if len(liste_temps)>0:
            liste_temps[-1] = "%.3f" % (float(liste_temps[-1])+2)
            listeur()
     
    def DNF():
        if len(liste_temps)>0:
            liste_temps[-1] = "DNF"
            listeur()
     
    def plein_ecran(x):
        fen.attributes("-fullscreen", x)
        if x == 1:
            fenetre.entryconfigure(0,label="Quitter le plein écran    [Echap]", command=lambda:plein_ecran(0))
        elif x == 0:
            fenetre.entryconfigure(0,label="Plein écran    [F11]", command=lambda:plein_ecran(1))
     
    #Variables
    flag = 0
    w = 20
    liste_temps = []
    last_scramble=""
    stop = 0
    # ---------- Programme principal ----------
    fen = Tk()
    fen.bind("<KeyRelease>",inter_on)
    fen.bind("<Key>",inter_off)
    # ----- Widgets -----
    texte = Label(fen,text="Veuillez patienter",font="{Tahoma} 18")
    texte.pack(pady=5)
     
    dernier_melange = Label(fen,text=last_scramble,font="{Tahoma} 14")
    dernier_melange.pack(pady=5)
     
    nombre = StringVar()
    nombre.set("0.000")
    temp = Label(fen,textvariable=nombre,font="{Tahoma} 200").pack()
     
    stats = Frame(fen)
    stats.pack()
     
    frame = Frame(stats)
    frame.grid(row=0,column=0,pady=10, padx=10)
     
    temps = Text(frame,font="{Tahoma} 18",width=31,height=7,wrap=WORD)
    temps.grid(column=0, row=0)
     
    scrollbar = Scrollbar(frame,command=temps.yview)
    scrollbar.grid(column=1, row=0, sticky=S+N)
     
    averages = Frame(stats,borderwidth=2,relief=GROOVE)
    averages.grid(row=0,column=1,padx=10,pady=5)
     
    best = Label(averages,text="best : 0.000",font="{Tahoma} 18")
    best.pack(padx=10)
     
    worst = Label(averages,text="worst : 0.000",font="{Tahoma} 18")
    worst.pack(padx=10)
     
    ao_totale = Label(averages,text="ao : 0.000",font="{Tahoma} 18")
    ao_totale.pack(padx=10)
     
    ao_5 = Label(averages,text="best ao 5 : 0.000",font="{Tahoma} 18")
    ao_5.pack(padx=10)
     
    ao_12 = Label(averages,text="best ao 12 : 0.000",font="{Tahoma} 18")
    ao_12.pack(padx=10)
     
    ao_100 = Label(averages,text="best ao 100 : 0.000",font="{Tahoma} 18")
    ao_100.pack(padx=10)
    # ----- Menu -----
    Cube = Menu(fen)
     
    fenetre = Menu(Cube,tearoff=0)
    fenetre.add_command(label="Plein écran    [F11]", command=lambda:plein_ecran(1))
    fenetre.add_command(label="Afficher une bite", command=lambda:print("une bite"))
    fenetre.add_separator()
    fenetre.add_command(label="Quitter", command=fen.destroy,)
    Cube.add_cascade(label="Fenêtre", menu=fenetre)
     
    Cubes = Menu(Cube, tearoff=0)
    Cubes.add_command(label="2x2x2", command=lambda:change(10))
    Cubes.add_command(label="3x3x3", command=lambda:change(20))
    Cubes.add_command(label="4x4x4", command=lambda:change(40))
    Cube.add_cascade(label="Catégorie", menu=Cubes)
     
    effacage = Menu(Cube, tearoff=0)
    effacage.add_command(label="Dernier temps", command=lambda:effacer(-1))
    effacage.add_command(label="Premier temps", command=lambda:effacer(0))
    Cube.add_cascade(label="Effacer", menu=effacage)
     
    penalite = Menu(Cube, tearoff=0)
    penalite.add_command(label="+2", command=plus_2)
    penalite.add_command(label="DNF", command=DNF)
    Cube.add_cascade(label="Pénalités", menu=penalite)
     
    fen.config(menu=Cube)
     
    melange(20)
    fen.mainloop()
    EDIT : J'ai modifié la ligne 43 du programme avec "fen.after_idle(lambda: nombre.set(y))" dans le cas présent.

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

    Citation Envoyé par Pixelon Voir le message
    je me suis penché sur le lien et j'ai effectué des modifications dans mon programme mais je crois que le problème est aggravé

    EDIT : J'ai modifié la ligne 43 du programme avec "fen.after_idle(lambda: nombre.set(y))" dans le cas présent.
    chrono appelle listeur qui appelle... et toutes ces fonctions "touchent" au GUI depuis un thread séparé.
    note: s'il suffisait de changer une ligne, je vous l'aurais dit... Là, il faut reprendre le programme pour voir dans quel contexte vos fonctions sont appelées. Ca demande de comprendre ce que çà fait et pour intéressant que cela peut être, j'ai (malheureusement pour vous) un rizotto sur le feu.

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

  7. #7
    Membre chevronné
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2013
    Messages
    1 608
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2013
    Messages : 1 608
    Points : 2 072
    Points
    2 072
    Par défaut
    Aucun plantage chez moi avec le premier programme.
    Pas d'aide par mp.

  8. #8
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    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 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Citation Envoyé par marco056 Voir le message
    Aucun plantage chez moi avec le premier programme.
    L'inconvénient d'un défaut de construction, c'est que les problèmes ne sont pas toujours reproductibles...

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

  9. #9
    Futur Membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Février 2015
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Aude (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Février 2015
    Messages : 7
    Points : 8
    Points
    8
    Par défaut
    D'accord, donc si j'ai bien compris, le problème viendrait du fait que certaines fonctions se "chevauchent" et modifient le GUI (même si j'ignore de quoi il s'agit précisément je peux le deviner) en même temps, ce qui dérangerait python ?
    Merci du temps que vous passez à me repondre

  10. #10
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 687
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 687
    Points : 30 980
    Points
    30 980
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Pixelon Voir le message
    sauf pour l'astuce avec le module "operator" qui est un peu plus complexe ^^' mais je le ferai plus tard promis (si j'arrive à comprendre toute fois)
    Pas compliqué: ce module apporte des fonctions qui se comportent comme des opérations arithmétiques de base. operator.add(x, y) renvoie l'addition de x et de y, operator.sub(x, y) renvoie la soustraction et etc pour mult et div.
    Comme le nom d'une fonction est un élément manipulable en Python (alors qu'un opérateur de base ne l'est pas), ça permet justement de rendre une opération arithmétique facilement modulable (non seulement les opérandes pourront varier mais aussi les opérateurs dont la fonction correspondante peut être initialement recopié dans des variables lesquelles se comportent alors comme l'opérateur dont elles reçoivent la copie).

    Ceci dit, même sans ça, la factorisation reste toujours possible dans une syntaxe basique...
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    if actuel_mouvement in (0,2,4):
        tmp=actuel_mouvement+1
    else:
        tmp=actuel_mouvement-1
    # if
     
    if precedent_mouvement != tmp :
        n=n+1
        move=liste[actuel_mouvement][particularite]
        scramble = "%s %s" % (scramble, move)
        precedent_mouvement = actuel_mouvement
    # if

    De plus, je t'ai introduit les opérateurs parce que je pense que d'une façon générale ça peut t'aider dans tes algos mais ici, très spécifiquement, ils ne sont pas nécessaires...
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    if precedent_mouvement != (actuel_mouvement+1 if actuel_mouvement in (0, 2, 4) else actuel_mouvement-1):
        n=n+1
        move=liste[actuel_mouvement][particularite]
        scramble = "%s %s" % (scramble, move)
        precedent_mouvement = actuel_mouvement
    # if
    Où ici j'utilise la syntaxe spécifique python valeurX if expression_booleenne else valeurY qui renvoie "valeurX" ou "valeurY" selon la validité V/F de l'expression booléenne. Et qu'on peut aussi remplacer (selon son humeur) par une autre analogue expression_booleenne and valeurX or valeurY => variete_des_mouvements=x < 40 and 3 or 6. Et tu remarqueras aussi (j'espère) un façon plus souple de formatter les strings...

    PS: bravo pour avoir fait l'effort de mettre des noms de variables explicites. Ca fait plaisir
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

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

    Citation Envoyé par Pixelon Voir le message
    D'accord, donc si j'ai bien compris, le problème viendrait du fait que certaines fonctions se "chevauchent" et modifient le GUI (même si j'ignore de quoi il s'agit précisément je peux le deviner) en même temps, ce qui dérangerait python ?
    Les interfaces graphiques et les (soucis de synchronisation) threads sont des technologies qui ont une trentaine d'années. La littérature et les tutos sont suffisamment abondants et méritent d'être lus et compris avant de les utiliser à tâtons.

    J'ai pris le temps de lire votre code:
    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
    def chrono():
        montemps=time()
        while flag == 1:
            y="%.3f" % (time()- montemps)
            nombre.set(y)
        liste_temps.append(y)
        listeur()
     
    def inter_on(event):
        global flag,stop
        if flag == 0 and stop == 0 and event.keysym == "space":
            t = threading.Thread(target=chrono, daemon=True)
            flag = 1
            t.start()
            stop = 1
        else:
            stop = 0
     
    def inter_off(event):
        global flag
        if event.keysym == "F11":
            plein_ecran(1)
        elif event.keysym == "Escape":
            plein_ecran(0)
        if flag == 1:
            flag = 0
            melange(w)
    Tout vos soucis viennent de la fonction chrono.
    Pas besoin de boucler à 3Ghz pour compter le temps qui passe.
    En programmation séquentielle, on ajoute un petit sleep pour ne pas bouffer inutilement le CPU:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    def chrono():
        montemps=time()
        while flag == 1:
            y="%.3f" % (time()- montemps)
            nombre.set(y)
            sleep(0.01)
    Évidement, appeler une fonction qui ne se termine pas dans le callback d'un GUI bloque toutes les mises à jours et aussi la prise en compte de l’événement "fin".
    D'où l'idée de vouloir utiliser des threads qui est plutôt "violente".
    Un GUI sait très bien faire cela:
    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
    import tkinter as tk
    import time
     
    timer_id = None
    start_time = None
     
    def start_timer(delay=200):
        global timer_id, start_time
     
        if start_time is None:
            start_time = time.time()
            elapsed = 0
        else: 
            elapsed = time.time() - start_time
        print (elapsed)
        label['text'] = "%.3f" % elapsed
        timer_id = root.after(delay, start_timer)
     
    def stop_timer():
        global timer_id, start_time
     
        if timer_id != None:
            label.after_cancel(timer_id)
            elapsed = time.time() - start_time
            print (elapsed)
            start_time = timer_id = None
     
    root = tk.Tk()
    label = tk.Label(root, text='0.000', width=5)
    label.pack()
    root.bind("<KeyRelease>", lambda e: start_timer())
    root.bind("<Key>", lambda e: stop_timer())
    tk.mainloop()
    if timer_id != None: stop_timer()
    C'est un exemple que vous devriez pouvoir adapter à votre code.

    Je ne peux que vous recommander la lecture du Swinnen. Vous y trouverez pas mal d'exemples d'utilisation de tkinter et des explications sur "comment çà marche et comment les utiliser".
    note: et aussi des exemples ou il modifie le GUI depuis un thread car "officiellement" çà devrait fonctionner (et çà ne fonctionne pas si mal si on reste "sobre" et qu'on a de la chance).

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

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

Discussions similaires

  1. [Access 2003] Plantage aléatoire
    Par Strontium dans le forum Access
    Réponses: 1
    Dernier message: 04/06/2007, 15h07
  2. Réponses: 2
    Dernier message: 06/03/2007, 11h07
  3. Plantage aléatoire à l'ouv. de fichiers ext.
    Par Stutak dans le forum Access
    Réponses: 3
    Dernier message: 09/08/2006, 19h36
  4. Comportement aléatoire du programme
    Par afrikha dans le forum Agents de placement/Fenêtres
    Réponses: 9
    Dernier message: 12/12/2005, 15h15
  5. Réponses: 15
    Dernier message: 07/07/2005, 11h05

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