- Réviseur en python - Problème

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Bonjour,

j'ai actuellement un problème avec mon programme en python.

Il s'agit d'un programme qui demande votre vocabulaire, l'enregistre et je voudrais qu'il lorsque l'on redémarre le programme, puisse me remettre les anciens mots que je lui ai donné.

Je vous transmet ci-joint mon programme.

En attente de vos réponse,

amicalement

Astronight

PS : Pour que le programme fonctionne il faut mettre dans le même dossier un fichier nommé "donnees.csv"

 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
 #-*- coding: utf-8 -*-

import os
import pickle
from random import *
import csv

dico1={}
type(dico1)



demande=True
while(demande):

    wordvo=input("mettez votre voc fr ici :")
    wordvf=input("mettez la traduction ici :")
    dico1[wordvf] = wordvo
    question=input("voulez vous mettre plus de voc ?")
    if question=='oui':
        demande=True

    else:
        demande = False



def writ():
    w=csv.writer(open("donnees.csv",'a'))
    for key, val in dict.items(voc_recupere):
        w.writerow([key, val])

with open('donnees.csv', 'ab') as fichier:
    mon_pickler = pickle.Pickler(fichier)
    mon_pickler.dump(dico1)
# enregistrement


with open('donnees.csv','rb') as fichier:

   mon_depickler = pickle.Unpickler(fichier)
   voc_recupere = mon_depickler.load()
# Lecture des objets contenus dans le fichier.
writ()
##fonction()

cles = []

rep=10
while(rep<20):

    for i in voc_recupere.keys():
        cles.append(i)

    temp = choice(cles)

    print(voc_recupere[temp])
    trad=input("écrivez la traduction :")

    print(trad==temp)
    while(trad!=temp):
        print ("c'est faux recommence")
        trad=input("écrivez la traduction :")

Édité par Astronight

+0 -0
Staff

Bonjour Astronight,

Comme le demande Aabu, pourrais tu nous préciser ce qui ne fonctionne pas ? Je vois que tu utilise plusieurs choses pour enregistrer (pickle, csv…). Laquelle te pose problème ? Quel erreur as tu ?

Je pense que ta fonction `writ() ne fonctionne pas, a vu de nez, mais il nous faut plus de précision pour t'aider.

+1 -0
Auteur du sujet

Tout d'abord, merci de votre rapide réponse. Ensuite, je voudrais que le programme me demande mon voc fr et la traduction puis l'enregistre dans le fichier CSV. Puis m'interroge dessus en me demandant la traduction du mot. Après je voudrais éteindre le programme, le relancer et pareil lui donner des mots mais qu'il ajoute à l'ancienne liste dans le fichier CSV et m'interroge sur l'ensemble des mots (ceux d'avant et d'armes le redémarrage du programme)

Le problème est qu'il enregistre bien dans le fichier (avec des caractéres bizarres) Mais lorsque je relance le programme, il me donne les anciens mots sans prendre compte des nouveaux que je lui ai fournis.

J'espère avoir été clair.XD

+0 -0
Staff

Cette réponse a aidé l'auteur du sujet

Salut,

Tu mélanges deux méthodes d'enregistrement pour tes mots.

  • Stocker les mots dans un fichier CSV (c'est-à-dire un fichier texte, où les champs (ici un mot et sa traduction) sont séparés par des virgules).
  • Stocker des objets Python sérialisés (c'est-à-dire un fichier binaire, où ton dictionnaire Python est directement enregistré comme une suite d'octets, illisibles pour un humain).

Il faut que tu choisisses une des deux méthodes. La première méthode va te permettre de pouvoir lire le fichier avec un autre logiciel (éditeur de texte, tableur…), pas la deuxième.

Voilà l'idée générale de ce que tu dois faire. Les détails dépendent de la méthode que tu vas choisir.

  1. Demander à l'utilisateur de rentrer des mots.
  2. Vérifier si un fichier de mots existe déjà.
  3. Si oui, ouvrir ce fichier, et lire son contenu (par exemple dans un dictionnaire).
  4. Sinon le créer.
  5. écrire le contenu précédent (si le fichier existait déjà) et en plus le nouveau contenu.

Édité par Aabu

+1 -0
Staff

Cette réponse a aidé l'auteur du sujet

Bon on va le faire dans l'ordre parce que tu semble être débutant en Python.

Voila comment je pense ton programme devrait être amélioré.

Commençons par faire des fonctions pour chacune des taches principales de ton application :

  • Demander de nouveaux mots et compléter un dico
  • Interroger sur un dico
  • Sauvegarder un dico
  • Le charger

Je vais principalement te mettre des codes commentés, n'hésite pas à poser des question dessus

Demander de nouveaux mots

Rien de bien compliqué

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# Une fonction par tâche élémentaire, c'est plus simple à long terme.
def ajouter_un_mot(dico):
    """Fonction demandant un mot à un utilisateur et l'ajoute au dico si il n'est pas déjà présent"""
    wordvo=input("mettez votre voc fr ici :")
    wordvf=input("mettez la traduction ici :")
    # Ici je préfère vérifier que le mot n'existe pas déjà et prévenir l'utilisateur si c'est le cas.
    if wordvf in dico:
        print("Le mot", wordvf, "est déjà présent dans le dictionnaire, l'ancienne traduction", dico[wordvf], "va être remplacé par", wordvo)
    dico[wordvf] = wordvo

# La fonction qui va compléter ton dico
def demander_mots(dico):
    """Demande à l'utilisateur une série de mots"""
    question = 'oui'
    # Petite modif : pas besoin de faire un if/else ici et utiliser une autre variable
    while question=='oui':
        ajouter_un_mot(dico)
        question=input("voulez vous mettre plus de voc ?")

Interroger sur un dico

Je ne suis pas sûrs que ton code marche, en voici un simple qui doit y ressembler

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
from random import sample

def interroger_voc(dico):
    """Interroger sur une série de vocabulaire"""
    # On demande à l'utilisateur combien de mots il veut réviser
    n_mot = int(input("Combien de mots voulez-vous réviser ?"))
    # Je prend N mot aléatoire. Attention il y a un bug : ça plantera si l'utilisateur veut plus de mot que
    # de mots dans le dico
    voc_select = sample(dico.items(), n_mot)

    # Pour chaque pair de mot qu'on a choisi...
    for mot_vf, mot_vo in voc_select:
        proposition = ""
        # On demande une traduction et on prévient l'utilisateur !
        while proposition != mot_vf:
            proposition = input("écrivez la traduction de '{}':".format(mot_vo))
            if proposition != mot_vf:
                print("C'est faux, recommence")
        print("C'est Bon !")

Normalement là tu peux tester les deux pour vérifier que ça fonctionne en mettant les deux morceaux dans le même fichier et en rajoutant :

1
2
3
voc = {}
demander_mots(voc)
interroger_voc(voc)

Enregistrement / Lecture du fichier

Comme le dit Aabu, tu mélange deux solution. Le fichier CSV est un fichier texte tandis que pickle est un format binaire interne a Python.

Vu que je suis faignant je vais te le montrer avec pickle

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import pickle

def charger_doc_si_existe(nom_fichier):
    """Cette fonction va charger un fichier si il existe"""
    # On essai de charger le fichier, on renvoie un dico vide si ça ne marche pas    
    try:
        voc = pickle.load(open("toto.p", "rb"))
    except IOError:
        voc = {}
    return voc

def sauvegarder_voc(voc, nom_fichier):
    pickle.dump(voc, open("toto.p", "wb"))

L'ensemble

Maintenant il n'y a plus qu'à tout mettre ensemble. Par exemple en appelant les fonctions dans cet ordre :

1
2
3
4
5
nom_fichier = "toto.p"
voc = charger_doc_si_existe(nom_fichier)
demander_mots(voc)
sauvegarder_voc(voc, nom_fichier)
interroger_voc(voc)

Voila. Le programme est loin d'être parfait mais j'ai dut corriger les principaux problèmes.

Comprend-tu la logique ?

+6 -0

Il vaudrait mieux utiliser du CSV que du format binaire dans ton cas: on peut ainsi modifier les mots avec un simple éditeur de texte, ce qui peut être très pratique. En plus, le module csv en Python simplifie bien la tâche.

+0 -0
Staff

Cette réponse a aidé l'auteur du sujet

Si c'est juste pour stocker de simples clé,valeur, le module CSV standard de Python est complètement overkill.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# Chargement
with open('monfichier.csv') as csv:
    for line in csv:
        key, val = line.strip().split(',')
        dico[key] = val

# Sauvegarde
with open('monfichier.csv', 'w') as csv:
    for key, val in dico.items():
        csv.write('{},{}\n'.format(key, val))

Édité par nohar

I was a llama before it was cool

+3 -1
Auteur du sujet

Bonjour, merci pour vos réponses. Alors oui j'ai compris la logique mais en apportant les modifications que vous me conseillez, je rencontre deux erreurs.

 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
from random import sample
import pickle

# Une fonction par tâche élémentaire, c'est plus simple à long terme.
def ajouter_un_mot(dico):
    """Fonction demandant un mot à un utilisateur et l'ajoute au dico si il n'est pas déjà présent"""
    wordvo=input("mettez votre voc fr ici :")
    wordvf=input("mettez la traduction ici :")
    # Ici je préfère vérifier que le mot n'existe pas déjà et prévenir l'utilisateur si c'est le cas.
    if wordvf in dico:
        print("Le mot", wordvf, "est déjà présent dans le dictionnaire, l'ancienne traduction", dico[wordvf], "va être remplacé par", wordvo)
    dico[wordvf] = wordvo

# La fonction qui va compléter ton dico
def demander_mots(dico):

    """Demande à l'utilisateur une série de mots"""
    question = 'oui'
    # Petite modif : pas besoin de faire un if/else ici et utiliser une autre variable
    while question=='oui':
        ajouter_un_mot(dico)
        question=input("voulez vous mettre plus de voc ?")


def interroger_voc(dico):
    """Interroger sur une série de vocabulaire"""
    # On demande à l'utilisateur combien de mots il veut réviser
    n_mot = int(input("Combien de mots voulez-vous réviser ?"))
    # Je prend N mot aléatoire. Attention il y a un bug : ça plantera si l'utilisateur veut plus de mot que
    # de mots dans le dico
    voc_select = sample(dico.items(), n_mot)

    # Pour chaque pair de mot qu'on a choisi...
    for mot_vf, mot_vo in voc_select:
        proposition = ""
        # On demande une traduction et on prévient l'utilisateur !
        while proposition != mot_vf:
            proposition = input("écrivez la traduction de '{}':".format(mot_vo))
            if proposition != mot_vf:
                print("C'est faux, recommence")
        print("C'est Bon !")


voc = {}
demander_mots(voc)
interroger_voc(voc)



def charger_doc_si_existe(nom_fichier):
    """Cette fonction va charger un fichier si il existe"""
    # On essai de charger le fichier, on renvoie un dico vide si ça ne marche pas    
    try:
        voc = pickle.load(open("donnees.csv", "rb"))
    except IOError:
        voc = {}
    return voc

def sauvegarder_voc(voc, nom_fichier):
    pickle.dump(voc, open("donnees.csv", "wb"))


nom_fichier = "donnees.csv"
voc = charger_doc_si_existe(nom_fichier)
demander_mots(voc)
sauvegarder_voc(voc, nom_fichier)
interroger_voc(voc)

Je me retrouve avec cette erreur :

1
2
3
4
5
6
7
Traceback (most recent call last):
  File "A:\réviseur\teste.py", line 77, in <module>
    voc = charger_doc_si_existe(nom_fichier)
  File "A:\réviseur\teste.py", line 67, in charger_doc_si_existe
    voc = pickle.load(open("donnees.csv", "rb"))
_pickle.UnpicklingError: invalid load key, '
'.

ensuite avec ce code :

 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
from random import sample
import pickle

# Une fonction par tâche élémentaire, c'est plus simple à long terme.
def ajouter_un_mot(dico):
    """Fonction demandant un mot à un utilisateur et l'ajoute au dico si il n'est pas déjà présent"""
    wordvo=input("mettez votre voc fr ici :")
    wordvf=input("mettez la traduction ici :")
    # Ici je préfère vérifier que le mot n'existe pas déjà et prévenir l'utilisateur si c'est le cas.
    if wordvf in dico:
        print("Le mot", wordvf, "est déjà présent dans le dictionnaire, l'ancienne traduction", dico[wordvf], "va être remplacé par", wordvo)
    dico[wordvf] = wordvo

# La fonction qui va compléter ton dico
def demander_mots(dico):

    """Demande à l'utilisateur une série de mots"""
    question = 'oui'
    # Petite modif : pas besoin de faire un if/else ici et utiliser une autre variable
    while question=='oui':
        ajouter_un_mot(dico)
        question=input("voulez vous mettre plus de voc ?")


def interroger_voc(dico):
    """Interroger sur une série de vocabulaire"""
    # On demande à l'utilisateur combien de mots il veut réviser
    n_mot = int(input("Combien de mots voulez-vous réviser ?"))
    # Je prend N mot aléatoire. Attention il y a un bug : ça plantera si l'utilisateur veut plus de mot que
    # de mots dans le dico
    voc_select = sample(dico.items(), n_mot)

    # Pour chaque pair de mot qu'on a choisi...
    for mot_vf, mot_vo in voc_select:
        proposition = ""
        # On demande une traduction et on prévient l'utilisateur !
        while proposition != mot_vf:
            proposition = input("écrivez la traduction de '{}':".format(mot_vo))
            if proposition != mot_vf:
                print("C'est faux, recommence")
        print("C'est Bon !")


voc = {}
demander_mots(voc)
interroger_voc(voc)

def charger_doc_si_existe(nom_fichier):
    # Chargement
    with open('donnees.csv') as csv:
        for line in csv:
            key, val = line.strip().split(',')
            dico[key] = val

def sauvegarder_voc(voc, nom_fichier):
    # Sauvegarde
    with open('donnees.csv', 'w') as csv:
        for key, val in dico.items():
            csv.write('{},{}\n'.format(key, val))

nom_fichier = "donnees.csv"
voc = charger_doc_si_existe(nom_fichier)
demander_mots(voc)
sauvegarder_voc(voc, nom_fichier)
interroger_voc(voc)

C'est cette erreur qui sort :

1
2
3
4
5
6
Traceback (most recent call last):
  File "A:\réviseur\teste.py", line 76, in <module>
    voc = charger_doc_si_existe(nom_fichier)
  File "A:\réviseur\teste.py", line 66, in charger_doc_si_existe
    key, val = line.strip().split(',')
ValueError: need more than 1 value to unpack

Si non encore merci pour votre aide.

PS: oui je suis débutant en python ;)

+0 -0

Perso je verrais un truc comme ça :

 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
import pickle
import random


def main():
    try:
        dictionary = pickle.load(open('dict.txt', 'rb'))
    except OSError:
        dictionary = {}
    except EOFError:
        dictionary = {}

    print("Type Return to exit the program")
    if input("Add words [Y|1 / N|0] ? ").lower().strip() in 'oy1':
        while True:
            word = input("Word [FR] > ").strip()
            if not word:
                break
            traduction = input("Traduction [EN] > ").strip()
            if not traduction:
                break
            dictionary[word] = traduction
    else:
        while True:
            chosen = random.choice([_ for _ in dictionary.keys()])
            word = input("Traduction for '{}' > ".format(chosen)).strip()
            while word != dictionary[chosen]:
                word = input("Traduction for '{}' > ".format(chosen)).strip()
            print("Yeah ! You're right")
            if input("Continue [Y|1 / N|0] ?").lower().strip() in 'n0':
                break
    pickle.dump(open('dict.txt', 'wb'), dictionary)

if __name__ == '__main__':
    main()

Simple, efficace :)

Édité par Cithoran

Ma chaine YouTube ! | Seventh, un micro langage communautaire ! | Mon projet : Unamed (en pleine reprogrammation en C++11/SFML2.4) | Mon tuto sur Pygame !

+1 -0
Staff

Les deux fonctions load(file) et save(file) ne semblent pas servir à grand chose : plutôt utiliser pickle.load(file) et pickle.dump(obj, file).

Edit: Ah bah pfou t'as édité ton code sans rien dire, on ne comprend plus d'où vient ma remarque. :)

Édité par nohar

I was a llama before it was cool

+2 -0
Staff

Comment testes-tu le programme de folaefolc ?

Il suffit de ne rien taper du tout et d'appuyer sur entrée pour sortir de la boucle, en fait. Ce qui me fait dire que LIRE le code et essayer de le comprendre aurait peut-être été une bonne idée…

Édité par nohar

I was a llama before it was cool

+0 -0

Comment testes-tu le programme de folaefolc ?

Il suffit de ne rien taper du tout et d'appuyer sur entrée pour sortir de la boucle, en fait. Ce qui me fait dire que LIRE le code et essayer de le comprendre aurait peut-être été une bonne idée…

nohar

Bah en fait, il le print même dans son logiciel…

ThuleMalta - C#, PHP, Python/Django, Unity3D. mon blog

+1 -0
Auteur du sujet

nohar : je le copie dans un fichier en .py et je le lance avec f5. Kje : tu es en quelle versions parce que moi ça marche pas. J'ai envoyé plus haut les erreurs qui se produisait lors de l’exécution du programme.

+0 -0
Auteur du sujet

Bon j'ai recommencé.

 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
 #-*- coding: utf-8 -*-

import os
import pickle
from random import *
import csv

dico1={}
type(dico1)



demande=True
while(demande):

    wordvo=input("mettez votre voc fr ici :")
    wordvf=input("mettez la traduction ici :")
    dico1[wordvf] = wordvo
    question=input("voulez vous mettre plus de voc ?")
    if question=='oui':
        demande=True

    else:
        demande = False




def writ():
    w=csv.writer(open("donnees.txt",'a'))
    for key, val in dict.items(dico1):
        w.writerow([key, val])

with open('donnees.txt', 'ab') as fichier:
    mon_pickler = pickle.Pickler(fichier)
    mon_pickler.dump(dico1)
# enregistrement



cles = []

rep=10
while(rep<20):

    for i in dico1.keys():
        cles.append(i)

    temp = choice(cles)

    print(dico1[temp])
    trad=input("écrivez la traduction :")
    print(trad==temp)
    while(trad!=temp):
        print ("c'est faux recommence")
        trad=input("écrivez la traduction :")

Pour le moment ce code enregistre les mots dans un fichier nommé donnees.txt. Quand je lui donne du voc il me le fait réviser. Mais ce qu'il ne fait pas c'est prendre le voc enregistrer dans le fichier et me le faire réviser avec les autres. Comment faire pour qu'il le fasse ?

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte