Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème avec mon programme

Sujet résolu
    18 septembre 2017 à 18:18:29

    Bonjours (ou bonsoir ça dépend ;))

    Je cherche actuellement à créer un programme générant des noms à partir de "syllabes" et étant capable d'enregistrer les noms dans un fichier texte. Pour éviter que l'utilisateur ai toujours à rentrer le chemin vers le fichier texte j'ai fais en sorte que le programme demande si c'est la première fois que l'utilisateur utilise le programme. Si c'est le cas, il demande à celui de rentrer le chemin d'enregistrement. Le code créé alors au même emplacement le fichier texte et un fichier pickle qui contient le chemin absolu du fichier texte. Lors de l'enregistrement, le code lit le fichier pickle pour obtenir le fameux chemin. Et c'est là que ça coince !! :(

    Lorsque le fichier pickle est lu, j'obtiens l'erreur suivante : UnicodeDecodeError: 'utf-8' codec can't decode byte 0x80 in position 0: invalid start byte

    Voici le code des fonctions qui se chargent de créer, charger et sauvegarder:

    def creation():
        """Creer un fichier qui sert de base si l'utilisateur n'a jamais utilise le generateur"""
        emplacement = input("A quel emplacement voudrez-vous enregistrer le fichier (le nom du fichier est genere automatiquement) ?\n")
        with open(emplacement + "\generateur_de_nom.txt", "w") as ficow:
            ficow.write(NOUVEAU)
        with open(emplacement + "\generateur_emp_sauv.pickle", "wb") as sauv:
            print("Un fichier pickle va être créer pour sauvegarder le chemin de sauvegarde. Veillez a ne pas le supprimer")
            pickle.dump(emplacement + "\generateur_de_nom.txt", sauv)
    
    def charger():
        """Ouvre le fichier texte grâce au fichier pickle"""
        emplacement_c = input("Veuillez rentrer generateur_emp_sauv.pickle\n")
        with open(emplacement_c, "rb") as lecture:
            fichier = lecture.read()
            print(fichier) #DEBUGGAGE
        return fichier
    
    def sauvegarde():
        """Sauvegarde le nom dans le fichier texte"""
        emplacement_s = charger()
        print("Sauvegarde")
        with open(emplacement_s, "r") as lis:
            x = lis.readlines()
            if demande == 0:
                position = x.index("Noms de continents:\n")
            elif demande == 1:
                position = x.index("Noms de pays:\n")
            elif demande == 2:
                position = x.index("Nom de regions:\n")
            elif demande == 3:
                position = x.index("Nom de villes/villages:\n")
            changement = x.insert(position + 1, final)
            texte_final = "".join(changement)

    Si quelqu'un a la solution pour faire disparaitre l'erreur je suis preneur :)

    • Partager sur Facebook
    • Partager sur Twitter
      18 septembre 2017 à 18:57:02

      Je pense qu'il faut lire le fichier avec pickle.load().
      • Partager sur Facebook
      • Partager sur Twitter

      Blond, bouclé, toujours le sourire aux lèvres...

        18 septembre 2017 à 19:03:42

        Bonjour,

        Deja il y a plusieurs problèmes

        1er point:

        Avec pickle tu n'as pas besoin d'ouvrir quoi que ce soit, tu as juste a faire dump ou load

        2nd point :

        Tu pourrais avoir des soucis avec des liens comme ca, le mieux est d'utiliser path.join de la librairie os.

        3ème point:

        charger() peut te retourner None si l'url a une typo. Du coup sauvegarde() ouvre None ce qui peut poser aussi une erreur.

        -
        Edité par coni63 18 septembre 2017 à 19:09:24

        • Partager sur Facebook
        • Partager sur Twitter
        Anonyme
          18 septembre 2017 à 19:05:51

          Ligne 6, il n'est pas spécifié qu'on crée un fichier avec l'encodage UTF8, mieux vaut le savoir en précisant le paramètre encoding.

          Voir la documentation sur open.

          • Partager sur Facebook
          • Partager sur Twitter
            19 septembre 2017 à 7:57:34

            oldProgrammer a écrit: > Ligne 6, il n'est pas spécifié qu'on crée un fichier avec l'encodage UTF8, mieux vaut le savoir en précisant le paramètre encoding.

            Ligne 4, plutôt. Car ligne 6, le fichier est ouvert avec le mode b (binaire), donc sans encodage.

            • Partager sur Facebook
            • Partager sur Twitter
            Anonyme
              19 septembre 2017 à 8:51:36

              Arf j'ai pas fais gaffe au b. Du coup l'erreur ne vient pas de là je pense.
              • Partager sur Facebook
              • Partager sur Twitter
                19 septembre 2017 à 20:24:34

                Tout d'abord merci pou votre réponses qui m'ont bien aider :D

                LoupSolitaire a écrit:

                Je pense qu'il faut lire le fichier avec pickle.load().

                Oui maintenant ça marche mieux merci. Je sais pas pourquoi j'y ai pas pensé plus tôt...

                coni63 a écrit:

                Bonjour,

                Deja il y a plusieurs problèmes

                1er point:

                Avec pickle tu n'as pas besoin d'ouvrir quoi que ce soit, tu as juste a faire dump ou load

                2nd point :

                Tu pourrais avoir des soucis avec des liens comme ca, le mieux est d'utiliser path.join de la librairie os.

                3ème point:

                charger() peut te retourner None si l'url a une typo. Du coup sauvegarde() ouvre None ce qui peut poser aussi une erreur.

                -
                Edité par coni63 hier à 19:09

                Pour le premier point j'ai essayé de faire dump sans ouvrir le fichier en écriture mais python veut pas.

                J'ai suivi tes conseils pour le le chemin du fichier avec path.join, c'est corrigé. Par contre pour la typo j'avoue ne pas trop savoir comment contrer ça.

                Bon le problème du décodage unicode a été réglé mais j'ai encore besoin d'assistance :ange: 

                Evidemment quand un problème est réglé il faut toujours qu'il en apparaisse d'autres. J'ai réussi a en corrigé quelques uns mais il y en a un qui me pose une colle, surtout que je ne comprend pas d'où vient le problème. Tout d'abord le nouveau code:

                def creation():
                    """Creer un fichier qui sert de base si l'utilisateur n'a jamais utilise le generateur"""
                    emplacement = input("A quel emplacement voudrez-vous enregistrer le fichier (le nom du fichier est genere automatiquement) ?\n")
                    emplacement_bf = os.path.join(emplacement, "generateur_de_nom.txt")
                    print(emplacement_bf) #DEBUGGAGE
                    emplacement_bp = os.path.join(emplacement, "generateur_emp_sauv.pickle")
                    print(emplacement_bp) #DEBUGGAGE
                    with open(emplacement_bf, "w") as ficow:
                        ficow.write(NOUVEAU)
                    with open(emplacement_bp, "wb") as sauv:
                        print("Un fichier pickle va être créer pour sauvegarder le chemin de sauvegarde. Veillez a ne pas le supprimer")
                        pickle.dump(emplacement + "\generateur_de_nom.txt", sauv)
                
                def charger():
                    """Ouvre le fichier texte grâce au fichier pickle"""
                    emplacement_c = input("Veuillez rentrer generateur_emp_sauv.pickle\n")
                    with open(emplacement_c, "rb") as lecture:
                        fichier = pickle.load(lecture)
                        print(fichier) #DEBUGGAGE
                    return fichier
                
                def sauvegarde():
                    """Sauvegarde le nom dans le fichier texte"""
                    emplacement_s = charger()
                    print("Sauvegarde")
                    with open(emplacement_s, "r") as lis:
                        x = lis.readlines()
                        if demande == 0:
                            position = x.index("Noms de continents:\n")
                        elif demande == 1:
                            position = x.index("Noms de pays:\n")
                        elif demande == 2:
                            position = x.index("Nom de regions:\n")
                        elif demande == 3:
                            position = x.index("Nom de villes/villages:\n")
                        x.insert(position + 1, stockage)
                        print(x) #DEBUGGAGE
                        print(type(x)) #DEBUGGAGE
                        texte_final = "".join(x)



                Maintenant l'explication:

                Le problème vient maintenant de la fonction sauvegarde(). A la fin de celle-ci je demande a python de relever les lignes qui les lignes déjà écrites dans le fichier texte créé à la base. Ensuite le code insert le nom précédemment créé dans la liste en décalant d'un rang. Jusque là aucun problème. C'est à la dernière ligne que ça coince. Python est censé concaténé toutes les chaînes de caractères de la liste. Cependant a ce moment là il y a l'erreur TypeError: sequence item 4: expected str instance, NoneType found.

                Et je ne comprend vraiment pas d'où vient cette erreur :colere:. Pour trouver le programme j'ai mis des lignes de "debuggage" en quelque sorte. L'erreur dit que la variable x est de type NoneType alors que dans la ligne où je demande le type de x, le code affiche bien <class 'list'>.

                Si quelqu'un sait je suis preneur (je sais je me répète :p).

                -
                Edité par Firox 19 septembre 2017 à 20:37:31

                • Partager sur Facebook
                • Partager sur Twitter
                  19 septembre 2017 à 21:36:04

                  C'est pas la liste qui pose problème, c'est son contenu, il y a un None quelque part dedans (probablement à l'index 4).

                  Enfin, là j'ai fait que traduire le message d'erreur en français, donc si tu l'as lu, je sais pas si ça t'aide vraiment.

                  D'ailleurs si tu as bien lu le message d'erreur, il dit qu'il espérait un type str, à aucun moment il ne demande un type list. C'est important de lire calmement les messages d'erreurs, surtout que ceux de Python sont assez explicites contrairement à d'autres langages !

                  Je sais qu'on a tendance à rager un peu quand on tombe sur des bugs, mais c'est important de respirer un bon coup et de lire tranquillement ce que Python raconte, parce qu'en voulant se précipiter, on risque de partir dans la mauvaise direction, et donc, de perdre du temps.

                  EDIT : Au fait, x n'est vraiment pas le meilleur nom possible pour ta variable dans cette situation, en général c'est plutôt utilisé pour une variable numérique, entier ou flottant. Tout comme lis n'est pas vraiment logique, ça fait penser à une liste alors que dans ton cas c'est un pointeur vers un fichier.

                  A la limite si t'as pas d'inspiration, un bête L (minuscule) sera mieux que x pour une variable qui représente une liste.

                  -
                  Edité par LoupSolitaire 19 septembre 2017 à 21:44:08

                  • Partager sur Facebook
                  • Partager sur Twitter

                  Blond, bouclé, toujours le sourire aux lèvres...

                    19 septembre 2017 à 21:51:10

                    Bonjour,

                    JamesElric a écrit:

                    Pour le premier point j'ai essayé de faire dump sans ouvrir le fichier en écriture mais python veut pas.

                    J'ai suivi tes conseils pour le le chemin du fichier avec path.join, c'est corrigé. Par contre pour la typo j'avoue ne pas trop savoir comment contrer ça.

                    Deja désolé, j'étais un peu rouillé sur l'utilisation de pickle il faut bien l'ouvrir ^^

                    Ensuite pour ton code, je ne sais pas trop pourquoi tu veux donner la main a l'utilisateur pour la sauvegarde pickle. Tu peux le stocker avec ton script et enregistrer dedans l'url du fichier. Du coup si l'utilisateur de te fourni pas d'url, tu l'as dans pickle. Voila comment je verrais le code:

                    import os
                    import pickle
                    
                    def create_file():
                        emplacement = input("A quel emplacement voudrez-vous enregistrer le fichier (le nom du fichier est genere automatiquement) ?\n")
                        emplacement_bf = os.path.join(emplacement, "generateur_de_nom.txt")
                        open(emplacement_bf, 'a').close()   # creer un fichier vide (c'est l'objectif de la fonction)
                        with open('save.pickle', 'wb') as f:
                            pickle.dump(emplacement_bf, f)
                        return emplacement_bf               # pour avoir ensuite l'url directement
                    
                    def charger(save_file = None):
                        if save_file is None:               # si tu ne founi pas d'url il va chercher un pickle
                            try:
                                save_file = pickle.load(open("save.pickle", "rb"))
                            except:
                                print("Pas de sauvegarde")
                                return False
                    
                        with open(save_file, 'r') as f:
                            for line in f:
                                print(line)
                    
                    def generate(save_file = None):
                        if save_file is None:
                            save_file = create_file()                   # si tu ne fournis pas de fichier il en crée un
                    
                        with open(save_file, 'w') as f:
                            f.write("Hello World")                      # ecrire ce que tu veux dedans
                    
                    if __name__ == "__main__":
                        #create_file()           # creer le fichier vide a l'url voulu et sauvegarde l'url dans pickle
                        #generate()              # me demande l'url pour creer le fichier
                        #generate("F:/.../generateur_de_nom.txt")   # Ajoute Hello world au fichier
                        #charger()                                                                      # Affiche Hello World s'il trouve le pickle
                        #charger("F:/.../generateur_de_nom.txt")     # Affiche Hello World

                    Bon j'ai pas pris en compte ton contenu pour la sauvegarde par contre :D

                    Pour le code, ou est demande et stockage dans sauvegarde ? Si tu utilise des variable global ce n'est pas tip top, j'aurais tendance a te dire de les envoyer dans la fonction. 

                    Ensuite tu as peut etre un problème dans index, s'il te retourne None car il ne trouve pas ta phrase, alors tu insert a None + 1 o_O

                    Tu as peut-etre aussi un soucis avec join car readlines() retourne un string et non une liste, du coup le join n'as pas de sens. Ou alors j'ai raté qqch

                    • Partager sur Facebook
                    • Partager sur Twitter
                      19 septembre 2017 à 22:19:11

                      Merci je testerais ça demain.

                      Pour demande et stockage, je les ai mis dans la section MAIN dans une branche conditionnelle qui appelle la fonction creation().

                      Par contre j'ai 2 petites questions à propos de ton code:

                      - dans la fonction charger() on ne peut pas juste mettre return tout seul au lieu de préciser False vu que cette valeur n'est pas réutilisée ?

                      - je ne vois pas de fonction qui permet à save_file de devenir autre chose que None c'est normal ?

                      Sinon pour readlines() je suis aller vérifier ça retourne bien une liste. J'ai même rajouter une ligne affichant x et ça affiche bien une position. Je crois que c'est readline() sans s qui renvoie une chaîne de caractères.

                      • Partager sur Facebook
                      • Partager sur Twitter
                        19 septembre 2017 à 22:45:34

                        JamesElric a écrit:

                        - dans la fonction charger() on ne peut pas juste mettre return tout seul au lieu de préciser False vu que cette valeur n'est pas réutilisée ?

                        - je ne vois pas de fonction qui permet à save_file de devenir autre chose que None c'est normal ?

                        Sinon pour readlines() je suis aller vérifier ça retourne bien une liste. J'ai même rajouter une ligne affichant x et ça affiche bien une position. Je crois que c'est readline() sans s qui renvoie une chaîne de caractères.

                        Pour charger() je ne sais pas trop, je veux juste break la fin du code du coup je retourne False. Apres tu peux stocker un booleen et faire la 2eme partie du code que si le booleen est vrai

                        Save_file vaut None par defaut mais si tu appelles la fonction avec un paramètre alors il vaudra ce parametre. C'est pour cela que tu as 2 resultats differents pour :

                        generate()              # me demande l'url pour creer le fichier
                        generate("F:/.../generateur_de_nom.txt")   # Ajoute Hello world au fichier

                        Dans un cas save_file vaut None (1er cas) et dans l'autre il vaut l'url du fichier que je donne

                        En effet j'ai confondu readline et readlines. Peut tu donner un bout de ton fichier texte ? peut etre que tu peux parser les données autrement.

                        • Partager sur Facebook
                        • Partager sur Twitter
                          20 septembre 2017 à 20:22:44

                          Ça y est le problème est résolu maintenant :magicien:. Le problème venait en fait d'une autre fonction du programme que j'ai pas posté dans mes messages précédents. C'était la fonction qui doit générer le nom à introduire qui renvoyait None dans la liste à cause d'un break mal placé...

                          LoupSolitaire a écrit:

                          C'est pas la liste qui pose problème, c'est son contenu, il y a un None quelque part dedans (probablement à l'index 4).

                          Enfin, là j'ai fait que traduire le message d'erreur en français, donc si tu l'as lu, je sais pas si ça t'aide vraiment.

                          D'ailleurs si tu as bien lu le message d'erreur, il dit qu'il espérait un type str, à aucun moment il ne demande un type list. C'est important de lire calmement les messages d'erreurs, surtout que ceux de Python sont assez explicites contrairement à d'autres langages !

                          -
                          Edité par LoupSolitaire il y a environ 21 heures

                          Je savais que le problème venait de la liste mais je ne savais pas pourquoi il y avait None dedans. Quelques lignes de debuggages m'ont finalement permit de remonter au problème. En fait j'ai mis du temps à le trouver parce que je ne soupçonnais absolument pas cette fonction d'être la cause de l'erreur. Sinon pour information .join demande str mais il est utilisé pour concaténer les str dans des listes ;) (et peut être pour d'autres choses dont j'ignore l'existance).

                          coni63 a écrit:

                          Bonjour,

                          JamesElric a écrit:

                          Pour le premier point j'ai essayé de faire dump sans ouvrir le fichier en écriture mais python veut pas.

                          J'ai suivi tes conseils pour le le chemin du fichier avec path.join, c'est corrigé. Par contre pour la typo j'avoue ne pas trop savoir comment contrer ça.

                          Deja désolé, j'étais un peu rouillé sur l'utilisation de pickle il faut bien l'ouvrir ^^

                          Ensuite pour ton code, je ne sais pas trop pourquoi tu veux donner la main a l'utilisateur pour la sauvegarde pickle. Tu peux le stocker avec ton script et enregistrer dedans l'url du fichier. Du coup si l'utilisateur de te fourni pas d'url, tu l'as dans pickle. Voila comment je verrais le code:

                          import os
                          import pickle
                          
                          def create_file():
                              emplacement = input("A quel emplacement voudrez-vous enregistrer le fichier (le nom du fichier est genere automatiquement) ?\n")
                              emplacement_bf = os.path.join(emplacement, "generateur_de_nom.txt")
                              open(emplacement_bf, 'a').close()   # creer un fichier vide (c'est l'objectif de la fonction)
                              with open('save.pickle', 'wb') as f:
                                  pickle.dump(emplacement_bf, f)
                              return emplacement_bf               # pour avoir ensuite l'url directement
                          
                          def charger(save_file = None):
                              if save_file is None:               # si tu ne founi pas d'url il va chercher un pickle
                                  try:
                                      save_file = pickle.load(open("save.pickle", "rb"))
                                  except:
                                      print("Pas de sauvegarde")
                                      return False
                          
                              with open(save_file, 'r') as f:
                                  for line in f:
                                      print(line)
                          
                          def generate(save_file = None):
                              if save_file is None:
                                  save_file = create_file()                   # si tu ne fournis pas de fichier il en crée un
                          
                              with open(save_file, 'w') as f:
                                  f.write("Hello World")                      # ecrire ce que tu veux dedans
                          
                          if __name__ == "__main__":
                              #create_file()           # creer le fichier vide a l'url voulu et sauvegarde l'url dans pickle
                              #generate()              # me demande l'url pour creer le fichier
                              #generate("F:/.../generateur_de_nom.txt")   # Ajoute Hello world au fichier
                              #charger()                                                                      # Affiche Hello World s'il trouve le pickle
                              #charger("F:/.../generateur_de_nom.txt")     # Affiche Hello World

                          Bon j'ai pas pris en compte ton contenu pour la sauvegarde par contre :D

                          Pour le code, ou est demande et stockage dans sauvegarde ? Si tu utilise des variable global ce n'est pas tip top, j'aurais tendance a te dire de les envoyer dans la fonction. 

                          Ensuite tu as peut etre un problème dans index, s'il te retourne None car il ne trouve pas ta phrase, alors tu insert a None + 1 o_O

                          Tu as peut-etre aussi un soucis avec join car readlines() retourne un string et non une liste, du coup le join n'as pas de sens. Ou alors j'ai raté qqch

                          Merci pour ton code en tous cas. Il m'a bien aider pour optimiser le code et surtout l'alléger. Par contre pour d'obscures raisons la fonction charger() ne fonctionnait pas car le code lançait toujours la partie except même si le fichier existait donc j'ai dû réaranger à ma sauce :zorro:

                          • Partager sur Facebook
                          • Partager sur Twitter

                          Problème avec mon programme

                          × 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