Bagaimana cara menyimpan kamus ke file?

149

Saya memiliki masalah dengan mengubah nilai dict dan menyimpan dict ke file teks (formatnya harus sama), saya hanya ingin mengubah member_phonebidangnya.

File teks saya adalah format berikut:

memberID:member_name:member_email:member_phone

dan saya membagi file teks dengan:

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

Ketika saya mencoba mengubah yang member_phonedisimpan d, nilainya telah berubah tidak mengalir oleh kunci,

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

dan bagaimana cara menyimpan dict ke file teks dengan format yang sama?

XueYuan Wang
sumber

Jawaban:

277

Python memiliki modul acar hanya untuk hal semacam ini.

Fungsi-fungsi ini adalah semua yang Anda butuhkan untuk menyimpan dan memuat hampir semua objek:

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)

Fungsi-fungsi ini mengasumsikan bahwa Anda memiliki objfolder di direktori kerja Anda saat ini, yang akan digunakan untuk menyimpan objek.

Perhatikan bahwa pickle.HIGHEST_PROTOCOLini adalah format biner, yang tidak selalu nyaman, tetapi bagus untuk kinerja. Protokol 0adalah format teks.

Untuk menyimpan koleksi Python ada modul rak .

Zah
sumber
1
save_objsepertinya membutuhkan file tersebut obj/'+ name + '.pklsudah ada. Saya membuat kamus bernama Q, mengisinya, dan membuat panggilan. save_obj(Q, "Qtable")Saya mendapat kesalahan: FileNotFoundError: [Errno 2] No such file or directory: 'obj/Qtable.pkl'Bagaimana cara membuat file pada awalnya sebelum menulis ke sana?
Tusuk Gigi Anemone
1
@ToothpickAnemone digunakan wb+untuk membuat file, yaitu:with open('obj/'+ name + '.pkl', 'wb+')
andrey.s
2
@ andrey.s: Saya rasa apa yang Anda katakan tidak akan membuat perbedaan karena itu tidak mengatasi masalah.
martineau
3
@Toothpick Anemone: Menambahkan a +ke mode tidak akan mempengaruhi masalah Anda (andrey.s salah). Masalah Anda terdengar seperti itu karena satu atau dua hal. Agar save_obj()jawaban ini berfungsi, subdirektori bernama "obj"harus sudah ada karena open()tidak akan membuatnya secara otomatis. Kedua, argumen pertama save_obj()adalah objek Python yang akan disimpan, bukan nama subdirektori (meskipun tidak sepenuhnya jelas apa yang Anda maksud dengan panggilan Qcontoh save_obj(Q, "Qtable")). Anda dapat membuat direktori jika belum ada os.mkdir().
martineau
176

Pickle mungkin merupakan opsi terbaik, tetapi jika ada yang bertanya-tanya bagaimana cara menyimpan dan memuat kamus ke file menggunakan 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: Penampil file NPY

Franck Dernoncourt
sumber
4
untuk apa .item ()?
Gulzar
Mengapa jawaban ini kurang disukai dibandingkan jawaban "acar" @Zah? Lebih kompleks-ruang?
Nathan
1
@frank kemungkinan karena acar adalah bagian dari pustaka standar python di mana numpy adalah proyek independen.
Maxim Veksler
2
@Gulzar dari apa yang saya cari, np.load mengembalikan ndarray (melakukan pengungkapan type(read_dictionary)) dan .item () pada dasarnya mengubah elemen itu menjadi objek skalar python yang merupakan kamus seperti yang dinyatakan di sini
abhyudayasrinet
2
@Shai, apakah Anda sudah menginstal paket numpy ...?
Eben
32

Kami juga dapat menggunakan jsonmodul jika kamus atau beberapa data lain dapat dengan mudah dipetakan ke format 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" ) )

Solusi ini membawa banyak manfaat , misalnya berfungsi untuk Python 2.x dan Python 3.x dalam bentuk yang tidak berubah dan sebagai tambahan, data yang disimpan dalam format JSON dapat dengan mudah ditransfer di antara banyak platform atau program yang berbeda . Data ini juga dapat dibaca manusia .

simhumileco.dll
sumber
1
Pendekatan yang bagus, tetapi menurut saya tidak aman untuk digunakan opensecara langsung daripada konteks yang dibuat oleh with. Apakah ada jaminan, file handle akan ditutup jika json.dumpgagal?
Dr_Zaszuś
18

Saya tidak yakin apa pertanyaan pertama Anda, tetapi jika Anda ingin menyimpan kamus ke file, Anda harus menggunakan jsonperpustakaan. Lihat dokumentasi fungsi load dan put.

John
sumber
Mengapa json? Bahkan lebih mudah untuk membuang kamus Python ke file menggunakan "repr"
mguijarr
5
@mguijarr tetapi menguraikannya kembali tidaklah mudah. Plus json mudah diedit dengan tangan dan diimpor ke program lain.
kalhartt
1
Saya suka saran John - lihat posting ini untuk contoh yang baik dan sederhana stackoverflow.com/a/11027021/765827
jacanterbury
10

Simpan dan muat dict ke file:

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
sumber
9

Saya menyarankan untuk menyimpan data Anda menggunakan format JSON daripada format acar karena file JSON dapat dibaca manusia yang membuat proses debug Anda lebih mudah karena data Anda kecil. File JSON juga digunakan oleh program lain untuk membaca dan menulis data. Anda dapat membaca lebih lanjut di sini

Anda harus menginstal modul JSON, Anda dapat melakukannya dengan pip:

pip install json


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

Ini membuat file json dengan nama myfile.

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

Ini membaca dan menyimpan data myfile.json dalam objek data.

Kavin Sabharwal
sumber
3

Untuk kamus string seperti yang Anda hadapi, itu bisa dilakukan hanya dengan menggunakan kemampuan pemrosesan teks bawaan Python.

(Perhatikan ini tidak akan berfungsi jika nilainya adalah sesuatu yang lain.)

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')
martineau.dll
sumber
Ini tidak berfungsi pada kamus: file.write (':'. Join ([id] + values.split (':')) + '\ n') AttributeError: 'dict' object tidak memiliki atribut 'split'
Shai Alon
@ShaiAlon: Tidak dengan semuanya, tidak. Ini jelas tidak bekerja dengan mereka yang nilai-nilai string (yang memiliki split()metode) -yang merupakan topik pertanyaan ini. Kedengarannya seperti Anda mencoba menggunakannya di kamus kamus, jadi tidak, itu tidak akan berhasil dengan itu. Saya juga tidak menghargai suara negatif dari orang-orang karena mereka tidak benar-benar memahami pertanyaannya (dan dengan demikian konteks jawaban diberikan). Saya akan memperbarui jawaban saya untuk membuat saat menggunakannya akan sesuai, jadi tolong batalkan suara tidak suka Anda.
martineau
2

Kecuali jika Anda benar-benar ingin menyimpan kamusnya, menurut saya solusi terbaik adalah menggunakan csvmodul Python untuk membaca file. Kemudian, Anda mendapatkan baris data dan Anda dapat mengubah member_phoneatau apa pun yang Anda inginkan; terakhir, Anda dapat menggunakan csvmodul lagi untuk menyimpan file dalam format yang sama saat Anda membukanya.

Kode untuk membaca:

import csv

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

Kode untuk menulis:

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

Tentu saja, Anda perlu menyesuaikan change()fungsi Anda :

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.dll
sumber
apa yang dimaksud denganOf course, you need to adapt your change() function:
kRazzy R
1
dalam pertanyaan, a dict digunakan sedangkan csv berfungsi lebih seperti daftar
mguijarr
1

Saya belum menentukan waktunya tapi saya yakin h5 lebih cepat dari acar; ukuran file dengan kompresi hampir pasti lebih kecil.

import deepdish as dd
dd.io.save(filename, {'dict1': dict1, 'dict2': dict2}, compression=('blosc', 9))
kata-kata
sumber
0

Karena Pickle memiliki beberapa masalah keamanan dan lambat ( sumber ), saya akan menggunakan JSON, karena cepat, built-in, dapat dibaca manusia, dan dapat dipertukarkan:

import json
data = {'another_dict': {'a': 0, 'b': 1}, a_list: [0, 1, 2, 3]}
# e.g. file = './data.json' 
with open(file, 'w') as f: 
    json.dump(datastore, f)

Membaca juga sama mudahnya:

with open(file, 'r') as f:
    data = json.load(f)

Ini mirip dengan jawaban ini , tetapi mengimplementasikan penanganan file dengan benar.

Michael Dorner
sumber