Как сохранить словарь в файл?

139

У меня проблема с изменением значения dict и сохранением dict в текстовый файл (формат должен быть таким же), я только хочу изменить member_phoneполе.

Мой текстовый файл имеет следующий формат:

memberID:member_name:member_email:member_phone

и я разделил текстовый файл с помощью:

mdict={}
for line in file:
    x=line.split(':')
    a=x[0]
    b=x[1]
    c=x[2]
    d=x[3]
    e=b+':'+c+':'+d

    mdict[a]=e

Когда я пытаюсь изменить member_phoneсохраненный в d, значение изменилось не поток по ключу,

def change(mdict,b,c,d,e):
    a=input('ID')
    if a in mdict:
        d= str(input('phone'))
        mdict[a]=b+':'+c+':'+d
    else:
        print('not')

а как сохранить dict в текстовый файл с таким же форматом?

Сюэ Юань Ван
источник

Ответы:

258

Python имеет модуль pickle только для такого рода вещей.

Эти функции - все, что вам нужно для сохранения и загрузки практически любого объекта:

def save_obj(obj, name ):
    with open('obj/'+ name + '.pkl', 'wb') as f:
        pickle.dump(obj, f, pickle.HIGHEST_PROTOCOL)

def load_obj(name ):
    with open('obj/' + name + '.pkl', 'rb') as f:
        return pickle.load(f)

Эти функции предполагают, что у вас есть objпапка в вашем текущем рабочем каталоге, которая будет использоваться для хранения объектов.

Обратите внимание, что pickle.HIGHEST_PROTOCOLэто двоичный формат, который не всегда удобен, но хорош для производительности. Протокол 0представляет собой текстовый формат.

Для сохранения коллекций Python есть модуль shelve .

Zah
источник
1
save_objкажется, требует, чтобы файл obj/'+ name + '.pklуже существовал. Я создал словарь с именем Q, заполнил его и сделал вызов. save_obj(Q, "Qtable")Я получил ошибку: FileNotFoundError: [Errno 2] No such file or directory: 'obj/Qtable.pkl'как создать файл в первую очередь перед записью в него?
Зубочистка Анемон
1
@ToothpickAnemone используется wb+для создания файла, а именно:with open('obj/'+ name + '.pkl', 'wb+')
andrey.s
1
@ andrey.s: Я не думаю, что то, что вы говорите, будет иметь значение, потому что это не решает проблему.
Мартино
1
@Toothpick Anemone: добавление +в режим не повлияет на вашу проблему (andrey.s неверно). Ваша проблема звучит так, как будто это из-за одной или двух вещей. Чтобы save_obj()этот ответ работал, подкаталог с именем "obj"должен уже существовать, поскольку open()он не будет создан автоматически. Во-вторых, первый аргумент для save_obj()- это объект Python, который нужно сохранить, а не имя подкаталога (хотя не совсем понятно, что вы имели в виду Qв save_obj(Q, "Qtable")вызове примера ). Вы можете создать каталог, если он еще не завершен с os.mkdir().
Мартино
168

Pickle - это, пожалуй, лучший вариант, но в случае, если кому-то интересно, как сохранить и загрузить словарь в файл с помощью NumPy:

import numpy as np

# Save
dictionary = {'hello':'world'}
np.save('my_file.npy', dictionary) 

# Load
read_dictionary = np.load('my_file.npy',allow_pickle='TRUE').item()
print(read_dictionary['hello']) # displays "world"

К вашему сведению: просмотрщик файлов NPY

Франк Дернонкур
источник
4
для чего нужен .item ()?
Гульзар
Почему этот ответ менее одобрен, чем ответ "Zah"? Более сложный космос?
Натан
1
Возможность @frank, потому что pickle является частью стандартной библиотеки python, где numpy является независимым проектом.
Максим Векслер
2
@Gulzar из того, что я посмотрел, np.load возвращает ndarray (делает это type(read_dictionary)так), а .item () в основном преобразует этот элемент в скалярный объект python, который является словарём, как здесь
abhyudayasrinet
2
@Shai, вы установили пакет numpy ...?
Эбен
26

Мы также можем использовать jsonмодуль в случае, когда словари или другие данные могут быть легко сопоставлены с форматом JSON .

import json

# Serialize data into file:
json.dump( data, open( "file_name.json", 'w' ) )

# Read data from file:
data = json.load( open( "file_name.json" ) )

Это решение дает много преимуществ , например, работает для Python 2.x и Python 3.x в неизменном виде, и, кроме того, данные, сохраненные в формате JSON , могут быть легко переданы между различными платформами или программами . Эти данные также читаются человеком .

simhumileco
источник
Хороший подход, но я не думаю, что безопасно использовать openнапрямую вместо контекста, созданного with. Есть ли гарантия, дескриптор файла будет закрыт при json.dumpсбое?
Dr_Zaszuś
18

Я не уверен, что ваш первый вопрос, но если вы хотите сохранить словарь в файл, вы должны использовать jsonбиблиотеку. Посмотрите документацию по нагрузкам и расставьте функции.

Джон
источник
Почему джсон? Еще проще просто сбросить словарь Python в файл, используя «repr»
mguijarr
5
@mguijarr, но разобрать его не так просто. Плюс JSON легко редактировать вручную и импортировать в любую другую программу.
Kalhartt
1
Мне нравится предложение Джона - посмотрите этот пост для хорошего и простого примера stackoverflow.com/a/11027021/765827
jacanterbury
9

Сохраните и загрузите файл dict в файл:

def save_dict_to_file(dic):
    f = open('dict.txt','w')
    f.write(str(dic))
    f.close()

def load_dict_from_file():
    f = open('dict.txt','r')
    data=f.read()
    f.close()
    return eval(data)
junglejet
источник
3

Для словаря строк, такого как тот, с которым вы имеете дело, это можно сделать, используя только встроенные возможности обработки текста Python.

(Обратите внимание, что это не будет работать, если значения являются чем-то другим.)

with open('members.txt') as file:
    mdict={}
    for line in file:
        a, b, c, d = line.strip().split(':')
        mdict[a] = b + ':' + c + ':' + d

a = input('ID: ')
if a not in mdict:
    print('ID {} not found'.format(a))
else:
    b, c, d = mdict[a].split(':')
    d = input('phone: ')
    mdict[a] = b + ':' + c + ':' + d  # update entry
    with open('members.txt', 'w') as file:  # rewrite file
        for id, values in mdict.items():
            file.write(':'.join([id] + values.split(':')) + '\n')
Мартино
источник
Это не работает со словарями: file.write (':'. Join ([id] + values.split (':')) + '\ n') AttributeError: у объекта 'dict' нет атрибута 'split'
Шай Алон
@ShaiAlon: Не со всеми из них, нет. Это , безусловно , делает работу с теми , чьими значениями являются строками (которые имеют split()метод) -Какой является темой этого вопроса. Похоже, вы пытаетесь использовать его в словаре словарей, так что нет, он не будет работать с ними. Я также не ценю отрицательное голосование от людей, потому что они действительно не понимают вопрос (и таким образом контекст предоставленных ответов). Я обновлю свой ответ, чтобы при его использовании было бы уместно, поэтому, пожалуйста, отмените свое отрицательное голосование.
Мартино
3

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

Вам нужно установить модуль JSON, вы можете сделать это с помощью pip:

pip install json


# To save the dictionary into a file:
json.dump( data, open( "myfile.json", 'w' ) )

Это создает файл JSON с именем myfile.

# To read data from file:
data = json.load( open( "myfile.json" ) )

Это читает и сохраняет данные myfile.json в объекте данных.

Кавин Сабхарвал
источник
2

Если вы действительно не хотите хранить словарь, я думаю, что лучшим решением будет использование csvмодуля Python для чтения файла. Затем вы получаете строки данных, и вы можете изменить member_phoneили что угодно; наконец, вы можете csvснова использовать модуль, чтобы сохранить файл в том же формате, в котором вы его открыли.

Код для чтения:

import csv

with open("my_input_file.txt", "r") as f:
   reader = csv.reader(f, delimiter=":")
   lines = list(reader)

Код для написания:

with open("my_output_file.txt", "w") as f:
   writer = csv.writer(f, delimiter=":")
   writer.writerows(lines)

Конечно, вам нужно адаптировать свою change()функцию:

def change(lines):
    a = input('ID')
    for line in lines:
      if line[0] == a:
        d=str(input("phone"))
        line[3]=d
        break
    else:
      print "not"
mguijarr
источник
что подразумевается подOf course, you need to adapt your change() function:
kRazzy R
1
в вопросе использовался a, dict тогда как csv работает больше как список
mguijarr
1

Я не рассчитал это, но держу пари, что h5 быстрее, чем рассол; размер файла со сжатием почти наверняка меньше.

import deepdish as dd
dd.io.save(filename, {'dict1': dict1, 'dict2': dict2}, compression=('blosc', 9))
wordsforthewise
источник
-2

Быстрое и грязное решение: преобразовать dict в строку и сохранить в файл, например:

#dict could be anything:

savedict = open('savedict001.txt', 'w')
savedict.write(str(dict))
savedict.close()
Патрик Стейси
источник
Преобразование dict в str и сохранение не работает, особенно если в качестве ключей в строках используются pd.Series или np.ndarray.
Арпан Шривастава