Як зберегти словник у файлі?


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 є модуль соління саме для подібних речей.

Ці функції - це все, що вам потрібно для збереження та завантаження практично будь-якого об’єкта:

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 є модуль полки .


1
save_objСхоже, вимагає, щоб файл obj/'+ name + '.pklвже існував. Я створив словник з ім’ям Q, заповнив його і здійснив дзвінок. save_obj(Q, "Qtable")Я отримав помилку: FileNotFoundError: [Errno 2] No such file or directory: 'obj/Qtable.pkl'як створюється файл в першу чергу перед тим, як писати в нього?
Зубочистка Anemone

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"

FYI: Переглядач файлів NPY


4
для чого .item ()?
Гульзар

Чому ця відповідь менш прихильна, ніж відповідь "Соління" @Zah? Більш просторовий комплекс?
Натан

1
@frank можливість, оскільки мариновані колективи є частиною стандартної бібліотеки 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 , можуть легко передаватися між багатьма різними платформами чи програмами . Ці дані також читаються людиною .


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

18

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


Чому json? Ще простіше просто скинути словник Python у файл, використовуючи "
repr

5
@mguijarr, але проаналізувати його назад не так просто. Plus json легко редагувати вручну та імпортувати в будь-яку іншу програму.
kalhartt

1
Я як пропозицію Джона - побачити цей пост для хорошого і простого прикладу stackoverflow.com/a/11027021/765827
jacanterbury

9

Збережіть та завантажте дікт у файл:

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)

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, а не формат соління, оскільки файли 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"

що мається на увазі під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))

-2

Швидке та брудне рішення: перетворіть дікт у рядок та збережіть у файл, наприклад:

#dict could be anything:

savedict = open('savedict001.txt', 'w')
savedict.write(str(dict))
savedict.close()

Перетворення dict у str та збереження не працює особливо, коли у вас є ключі в рядках pd.Series чи np.ndarray.
Арпан Срівастава
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.