Не удается получить словарь для сохранения в .txt файл без синтаксической ошибки в Python

#python #python-3.x

#python #python-3.x

Вопрос:

Я добавляю в свой словарь 2 разных приема пищи и 2 разных количества единиц измерения, которые затем отлично сохраняются в моем текстовом файле, но затем, когда я выхожу из программы и перезагружаю файл, я получаю синтаксическую ошибку. (Также некоторые функции выглядят так, как будто они не завершены, но это только потому, что Stack Overflow сказал мне не добавлять весь код.

Пытался заставить словарь не запускаться как пустой словарь, но это ничего не решило.

 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()
  

После добавления нескольких записей в словарь я ожидаю, что смогу выйти из программы, загрузить резервную копию и, когда я наберу view, чтобы просмотреть свои записи, посмотреть, что я ранее добавил.Это то, что я получаю —

 PS C:UsersAlexDesktopPythonown_projectsmosh> 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
  

Комментарии:

1. Вы должны использовать pickle вместо оценки текстовый файл. Это более безопасный и стандартный способ сохранения объектов Python в файлы. В качестве альтернативы, вы также можете использовать json библиотеку, поскольку вы просто сохраняете словари.

2. pickle не безопаснее, чем eval , вектор атаки просто менее тривиален.

Ответ №1:

Вероятно, проблема вызвана тем, что в ваш файл не добавлены новые строки. Простым исправлением было бы: f.write(str(meals) "n")

Но писать код в текстовом файле, а затем оценивать его — плохая идея:

  • Файл всегда будет доступен для чтения только вашей программой на Python
  • Он подвержен синтаксическим ошибкам (как в вашем вопросе)
  • Это очень небезопасно. Вредоносный код может оказаться в вашем файле.

Пока вы храните в своем словаре только текст, цифры и true / false, он может быть очень четко представлен файлом JSON. Преимущество JSON в том, что он может быть прочитан практически любым языком программирования:

 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)
  

Если вы храните в своем файле более сложные объекты, возможно, экземпляры классов и т.д., Тогда вам следует посмотреть на pickle. Это еще одна встроенная библиотека и очень удобный способ сохранить практически все из вашей программы на Python. Как указал Клаус Д. в комментарии, pickle не безопаснее вашего подхода. Вы никогда не должны загружать объект pickle из источника, которому вы не доверяете.

 import pickle

with open("file.txt", "wb") as file:
    pickle.dump(data, file)

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

Ответ №2:

Я не совсем помню, как работает pretty print, но этот способ выполнения этого очень хрупкий. Вероятность того, что что-то не будет напечатано так, как вы ожидаете, довольно высока, что может привести к сбоям в работе, как сейчас.

Я рекомендую использовать более стандартный формат передачи данных, такой как CSV или JSON. Если ваши данные плоские, я рекомендую CSV. Если ваши данные более сложные, я рекомендую JSON.

Я немного отредактирую этот ответ с примерами обоих методов.

Пример CSV:

 import csv

# This is a list of dictionaries
data = [
    {
        'meal': 'breakfast',
        'units': 20
    },
    {
        'meal': 'lunch',
        'units': 40
    },
    {
        'meal': 'dinner',
        'units': 50
    }
]
# If you wanted the values for lunch, you could do data[1]['units']
# This says access the second value inside the data list,
# and get the value for the units in that dictionary

def write_data(file_path='meals.csv'):
    # 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:
        # Create a dictionary writer, telling it what columns to expect
        writer = csv.DictWriter(f, ['meal', 'units'])
        writer.writeheader()
        writer.writerows(data)

def read_data(file_path='meals.csv'):
    new_data = []
    # open the file for reading
    with open(file_path) as f:
        # Create a dictionary reader. It will figure things out automagically
        reader = csv.DictReader(f)
        for row in reader:
            print(row)
            new_data.append(row)
    return new_data

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

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

Пример JSON:

 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())
  

Комментарии:

1. Спасибо за это, я это реализовал, но у меня возникла новая проблема, при добавлении записей все работает нормально, когда я снова загружаю программу и просматриваю записи, она отображается идеально, но если я затем добавлю другую запись, это приведет к сбросу словаря.

2. @lammyalex Вы читаете файл при запуске вашей программы? Ваш файл CSV / JSON действует как ваше постоянное хранилище. Когда ваша программа запускается, в ней нет информации. Необходимо извлечь старую информацию из файла перед добавлением новой информации. Рабочий процесс должен выглядеть следующим образом: Используйте read_data () для получения данных из файла и сохранения выходных данных в переменной => внесите свои коррективы => запишите данные обратно в файл с помощью write_data. Также, пожалуйста, отметьте тот ответ, который вы выбрали в качестве ответа на свой вопрос 🙂

3. да, я читаю данные, затем вношу изменения, затем записываю данные, но когда я записываю данные, они стирают то, что в них было, и заменяют их только новой записью, которую я добавил, если это имеет смысл. И я отметил это сейчас, спасибо 🙂

4. @lammyalex Извините за задержку. Перешел в спящий режим. Ха, это странно. Могу ли я посмотреть, как вы сохраняете данные и как вы добавляете запись? Из вашего исходного сообщения похоже, что вы считываете данные в переменную data , но вы добавляете новые данные в переменную с именем meals . Это происходит и в вашем текущем коде? Вам нужно будет добавить данные в ту же переменную, в которую вы их считываете. Что-то вроде этого: gist.github.com/TheBeege/1d9a158dd04f590f30f0b243f7fbd027

5. Это здорово, спасибо, действительно ценю вашу помощь.

Ответ №3:

это должно сработать:

 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()