Come salvare un dizionario in un file?


139

Ho problemi con la modifica di un valore di dict e il salvataggio del dict in un file di testo (il formato deve essere lo stesso), voglio solo cambiare il member_phonecampo.

Il mio file di testo è il seguente formato:

memberID:member_name:member_email:member_phone

e ho diviso il file di testo con:

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

Quando provo a modificare l' member_phonearchiviazione d, il valore è cambiato e non scorre dalla chiave,

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

e come salvare il dict in un file di testo con lo stesso formato?

Risposte:


258

Python ha il modulo pickle proprio per questo tipo di cose.

Queste funzioni sono tutto ciò che ti serve per salvare e caricare quasi tutti gli oggetti:

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)

Queste funzioni presuppongono che tu abbia una objcartella nella tua attuale directory di lavoro, che sarà usata per memorizzare gli oggetti.

Si noti che pickle.HIGHEST_PROTOCOLè un formato binario, che potrebbe non essere sempre conveniente, ma è buono per le prestazioni. Il protocollo 0è un formato di testo.

Per salvare le raccolte di Python c'è il modulo shelve .


1
save_objsembra richiedere che il file obj/'+ name + '.pklesista già. Ho creato un dizionario chiamato Q, popolato e fatto la chiamata save_obj(Q, "Qtable")Ho ricevuto un errore: FileNotFoundError: [Errno 2] No such file or directory: 'obj/Qtable.pkl'come si crea il file in primo luogo prima di scriverlo?
Stuzzicadenti Anemone,

1
@ToothpickAnemone usa wb+per creare il file, cioè:with open('obj/'+ name + '.pkl', 'wb+')
andrey.s

1
@ andrey.s: non credo che ciò che dici farà alcuna differenza perché non risolve il problema.
martineau,

1
@Toothpick Anemone: l'aggiunta di +a alla modalità non avrà alcun effetto sul tuo problema (andrey.s non è corretto). Il tuo problema sembra essere dovuto a una o due cose. Perché save_obj()in questa risposta funzioni, una sottodirectory denominata "obj"deve già esistere perché open()non ne creerà una automaticamente. Secondo, il primo argomento a save_obj()è l'oggetto Python da salvare, non il nome della sottodirectory (anche se non è del tutto chiaro cosa intendevi con la chiamata Qnell'esempio save_obj(Q, "Qtable")). Puoi creare una directory se non esiste già con os.mkdir().
martineau,

168

Pickle è probabilmente l'opzione migliore, ma nel caso qualcuno si chieda come salvare e caricare un dizionario in un file usando 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: visualizzatore di file NPY


4
a cosa serve .item ()?
Gulzar,

Perché questa risposta è meno votata rispetto alla risposta "sottaceto" di @Zah? Più complesso di spazio?
Nathan,

1
Possibilità @frank perché pickle fa parte della libreria standard di Python in cui numpy è un progetto indipendente.
Maxim Veksler,

2
@Gulzar da quello che ho cercato, np.load restituisce un ndarray (facendo una rivelazione type(read_dictionary)così) e .item () fondamentalmente converte quell'elemento in un oggetto scalare in pitone che è un dizionario come indicato qui
abhyudayasrinet

2
@Shai hai installato il pacchetto numpy ...?
Eben,

26

Possiamo anche usare il jsonmodulo nel caso in cui dizionari o altri dati possano essere facilmente associati al formato 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" ) )

Questa soluzione offre numerosi vantaggi , per esempio opere per Python 2.xe e Python 3.x in forma inalterata e in aggiunta, i dati memorizzati in JSON formato possono essere facilmente trasferiti tra molte piattaforme o programmi diversi . Questi dati sono anche leggibili dall'uomo .


Buon approccio, ma non credo sia sicuro usare opendirettamente invece di un contesto creato da with. C'è una garanzia, l'handle del file verrà chiuso se json.dumpfallisce?
Dr_Zaszuś,

18

Non sono sicuro di quale sia la tua prima domanda, ma se vuoi salvare un dizionario in un file dovresti usare la jsonlibreria. Cerca la documentazione dei carichi e mette le funzioni.


Perché JSON? È ancora più semplice scaricare il dizionario Python in un file usando "repr"
mguijarr,

5
@mguijarr ma analizzarlo non è così facile. Inoltre json è facile da modificare a mano e importare in qualsiasi altro programma.
Kalhartt,

1
Mi piace il suggerimento di Giovanni - Vedi questo post per una buona e semplice esempio stackoverflow.com/a/11027021/765827
jacanterbury

9

Salva e carica dict su 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)

3

Per un dizionario di stringhe come quello con cui hai a che fare, potresti farlo usando solo le funzionalità di elaborazione del testo integrate di Python.

(Nota che non funzionerebbe se i valori fossero qualcos'altro.)

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

Questo non funziona sui dizionari: file.write (':'. Join ([id] + valori.split (':')) + '\ n') AttributeError: l'oggetto 'dict' non ha attributi 'split'
Shai Alon,

@ShaiAlon: non con tutti loro, no. E 'sicuramente fa lavoro con coloro i cui valori sono stringhe (che hanno un split()metodo) -che è l'argomento di questa domanda. Sembra che tu stia cercando di usarlo su un dizionario di dizionari, quindi no, non funzionerebbe con quelli. Inoltre non apprezzo i voti negativi delle persone perché non capiscono davvero la domanda (e quindi il contesto delle risposte fornite). Aggiornerò la mia risposta per rendere quando usarlo sarebbe appropriato, quindi per favore annulla il tuo voto negativo.
martineau,

3

Suggerirei di salvare i tuoi dati usando il formato JSON invece del formato pickle poiché i file JSON sono leggibili dall'uomo, il che rende il tuo debug più semplice poiché i tuoi dati sono piccoli. I file JSON vengono utilizzati anche da altri programmi per leggere e scrivere dati. Puoi leggere di più qui

Dovrai installare il modulo JSON, puoi farlo con pip:

pip install json


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

Questo crea un file json con il nome myfile.

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

Questo legge e archivia i dati myfile.json in un oggetto dati.


2

A meno che tu non voglia davvero mantenere il dizionario, penso che la soluzione migliore sia usare il csvmodulo Python per leggere il file. Quindi, ottieni righe di dati e puoi cambiare member_phoneo quello che vuoi; infine, è possibile utilizzare csvnuovamente il modulo per salvare il file nello stesso formato in cui è stato aperto.

Codice per la lettura:

import csv

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

Codice per la scrittura:

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

Ovviamente, devi adattare la tua change()funzione:

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"

cosa si intende perOf course, you need to adapt your change() function:
kRazzy R il

1
nella domanda, a è dict stato usato mentre csv funziona più come un elenco
mguijarr,

1

Non l'ho cronometrato ma scommetto che h5 è più veloce del pickle; la dimensione del file con compressione è quasi certamente più piccola.

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

-2

Soluzione rapida e sporca: converti il ​​dict in stringa e salva in file, ad es .:

#dict could be anything:

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

La conversione di dict in str e il salvataggio non funzionano specialmente quando si dispone di pd.Series o np.ndarray come chiavi nelle stringhe.
Arpan Srivastava,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.