1
votes

Impossible d'obtenir le dictionnaire à enregistrer dans un fichier .txt sans erreur de syntaxe en Python

J'ajoute à mon dictionnaire 2 repas différents et 2 quantités unitaires différentes, ce qui enregistre ensuite parfaitement dans mon fichier texte, mais lorsque je quitte le programme et recharge le fichier, j'obtiens une erreur de syntaxe. (De plus, certaines fonctions semblent ne pas être terminées, mais c'est simplement parce que Stack Overflow m'a dit de ne pas ajouter tout le code.

J'ai essayé de faire en sorte que le dictionnaire ne démarre pas comme un dictionnaire vide, mais cela n'a rien résolu. P >

PS C:\Users\Alex\Desktop\Python\own_projects\mosh> python diabetes.py
    Traceback (most recent call last):
      File "diabetes.py", line 24, in <module>
        load_dict_from_file()
      File "diabetes.py", line 22, in load_dict_from_file
        return eval(data)
      File "<string>", line 1
        {}lasagne': 12, 'fish and chips': 16}
                ^
    SyntaxError: invalid syntax

Après avoir ajouté plusieurs entrées au dictionnaire, je m'attends à pouvoir quitter le programme, charger de nouveau et quand je tape view pour regarder mes entrées, voir ce que j'ai précédemment ajouté. Voici ce que j'obtiens -

import pprint
import time

pretty = pprint.PrettyPrinter(width = 20)
meals = {}
command = ""
condition = False

f = open("meals.txt", "r+")
f.write(str(meals))
f.close()

def save_dict_to_file(meals):
    f = open("meals.txt", "r+")
    f.write(str(meals))
    f.close()

def load_dict_from_file():
    f = open("meals.txt", "r+")
    data = f.read()
    f.close()
    return eval(data)

load_dict_from_file()

def add_entry():
    meal = input("Enter name of meal: ").lower()
    units = int(input("Enter units needed: "))
    meals[meal] = units
    pretty.pprint(meals)
    save_dict_to_file(meals)

def remove_entry():

def help():

def view_dict():

def ending_message():

while True:
    command = input("> ").lower()
    if command == "help":
    help()
    elif command == "add":
        add_entry()
    elif command == "exit":
        save_dict_to_file(meals)
        ending_message()
        time.sleep(3)
        break
    elif command == "remove":
        remove_entry()
    elif command == "view":
        view_dict()


2 commentaires

Vous devriez utiliser pickle au lieu d'évaluer un fichier texte. C'est plus sûr et le moyen standard d'enregistrer des objets python dans des fichiers. Vous pouvez également utiliser la bibliothèque json puisque vous ne faites que sauvegarder des dictionnaires.


pickle n'est pas plus sûr que eval , le vecteur d'attaque est juste moins trivial.


3 Réponses :


0
votes

Je ne me souviens pas entièrement à quel point la jolie impression fonctionne, mais cette façon d'y parvenir est très fragile. La probabilité que quelque chose ne s'imprime pas de la manière que vous attendez est assez élevée, ce qui pourrait casser les choses telles qu'elles sont actuellement.

Je recommande d'utiliser un format de transmission de données plus standard comme CSV ou JSON. Si vos données sont plates, je recommande CSV. Si vos données sont plus complexes, je recommande JSON.

Je modifierai cette réponse momentanément avec des exemples des deux méthodes.

Exemple CSV:

import json

data = {
    'lunch': 10,
    'breakfast': 20,
    'dinner': 30
}

def write_data(file_path='meals.json'):
    # Open the file for writing without adding extra new lines
    # The with syntax will automatically close it for us
    with open(file_path, 'w', newline='') as f:
        json.dump(data, f)

def read_data(file_path='meals.json'):
    # open the file for reading
    with open(file_path) as f:
        new_data = json.load(f)
    return new_data

print('writing data...')
write_data()

print('reading data...')
print(read_data())


9 commentaires

Merci pour cela, je l'ai implémenté mais j'ai un nouveau problème, tout fonctionne bien lors de l'ajout d'entrées, lorsque je charge à nouveau le programme et que je regarde les entrées, il apparaît parfait, mais si j'ajoute ensuite une autre entrée, il se réinitialise le dictionnaire.


@lammyalex Lisez-vous le fichier au démarrage de votre programme? Votre fichier CSV / JSON fait office de stockage persistant. Lorsque votre programme démarre, il ne contient aucune information. Il doit récupérer les anciennes informations du fichier avant d'ajouter de nouvelles informations. Le workflow devrait ressembler à ceci: Utilisez read_data () pour récupérer les données du fichier et stocker la sortie dans une variable => effectuez vos ajustements => réécrivez les données dans le fichier avec write_data. Veuillez également indiquer la réponse que vous avez choisie comme réponse à votre question :)


oui, je lis les données, puis j'apporte des modifications, puis j'écris les données, mais lorsque j'écris les données, cela efface ce qui s'y trouvait et le remplace par la nouvelle entrée que j'ai ajoutée, si cela a du sens. Et je l'ai marqué maintenant merci :)


@lammyalex Désolé pour le retard. Est allé dormir. Huh, c'est bizarre. Puis-je voir comment vous stockez les données et comment vous ajoutez l'entrée? À partir de votre message d'origine, il semble que vous lisiez les données dans une variable data , mais vous ajoutez de nouvelles données à une variable appelée repas . Cela se produit-il également dans votre code actuel? Vous devrez ajouter des données à la même variable dans laquelle vous lisez les données. Quelque chose comme ceci: gist.github.com/TheBeege/1d9a158dd04f590f30f0b243


Pas de problème merci pour l'aide, je pensais que je le faisais dans le bon ordre. Voici le code complet du programme - github.com/lammyalex/Mealyalex/M -Planner / commit /…


Je pense que le référentiel est privé. Le lien ne fonctionne pas et je ne vois aucun référentiel répertorié sur votre profil. Vous devrez soit rendre le référentiel public, soit m'ajouter en tant que collaborateur. Mon nom d'utilisateur est le même sur Github qu'ici


Je viens de vous y ajouter maintenant. Merci


Je ne sais pas à quel point vous êtes familier avec Github, mais j'ai soumis une pull request.


C'est super merci, j'apprécie vraiment votre aide.



0
votes

ce besoin de fonctionner:

import pprint
import time
import os
pretty = pprint.PrettyPrinter(width = 20)
meals = {}
command = ""
condition = False
n = False
if not os.path.isfile('meals.txt'):
    f = open("meals.txt", "w+")
    f.write(str(meals))
    f.close()
else:
    n = True

def save_dict_to_file(meals):
    f = open("meals.txt", "w+")
    f.write(str(meals))
    f.close()

def load_dict_from_file():
    f = open("meals.txt", "r+")
    data = f.read()
    f.close()
    return eval(data)
if n:
    meals = load_dict_from_file()

def add_entry():
    meal = input("Enter name of meal: ").lower()
    units = int(input("Enter units needed: "))
    meals[meal] = units
    pretty.pprint(meals)
    save_dict_to_file(meals)
import os
def remove_entry():
    os.remove('meals.txt')

def help():
    pretty.pprint('help')

def view_dict():
    pretty.pprint(load_dict_from_file())

def ending_message():
    pretty.pprint('done')

while True:
    command = input("> ").lower()
    if command == "help":
        help()
    elif command == "add":
        add_entry()
    elif command == "exit":
        save_dict_to_file(meals)
        ending_message()
        time.sleep(3)
        break
    elif command == "remove":
        remove_entry()
    elif command == "view":
        view_dict()


0 commentaires

1
votes

Le problème est probablement dû au fait de ne pas ajouter de nouvelles lignes à votre fichier. Une solution simple serait: f.write (str (repas) + "\ n")

Mais écrire du code dans un fichier texte puis l'évaluer est une mauvaise idée:

  • Le fichier ne sera jamais lisible que par votre programme python
  • Il est sujet aux erreurs de syntaxe (comme dans votre question)
  • C'est très dangereux. Un code malveillant pourrait se retrouver dans votre fichier.
  • Tant que vous ne stockez que du texte, des nombres et vrai / faux dans votre dictionnaire, il peut être représenté très proprement par un fichier JSON. JSON a l'avantage de pouvoir être lu par pratiquement n'importe quel langage de programmation:

    import pickle
    
    with open("file.txt", "wb") as file:
        pickle.dump(data, file)
    
    with open("file.txt", "rb") as file:
        data = pickle.load(file)
    

    Si vous stockez des objets plus complexes dans votre fichier, peut-être des instances de classes, etc., alors vous devriez regarder au cornichon. C'est une autre bibliothèque intégrée et un moyen très pratique de stocker presque tout à partir de votre programme python. Comme Klaus D. l'a souligné dans un commentaire, le cornichon n'est pas plus sûr que votre approche. Vous ne devez jamais charger un objet pickle d'une origine à laquelle vous ne faites pas confiance.

    import json
    
    data = {
        "A": 1,
        "B": {"C": 2}
    }
    
    # write data to file
    with open("file.txt", "w") as file:
        file.write(json.dumps(data))
    
    # read data from file
    with open("file.txt", "r") as file:
        data = json.load(file)
    


    0 commentaires