Wie speichere ich ein Wörterbuch in einer Datei?

139

Ich habe Probleme beim Ändern eines Diktatwerts und beim Speichern des Diktats in einer Textdatei (das Format muss identisch sein). Ich möchte nur das member_phoneFeld ändern .

Meine Textdatei hat das folgende Format:

memberID:member_name:member_email:member_phone

und ich teile die Textdatei mit:

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

Wenn ich versuche, das member_phonegespeicherte zu ändern d, hat sich der Wert geändert und fließt nicht durch den Schlüssel.

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

und wie speichere ich das Diktat in einer Textdatei mit demselben Format?

XueYuan Wang
quelle

Antworten:

258

Python hat das Pickle- Modul nur für diese Art von Dingen.

Diese Funktionen sind alles, was Sie zum Speichern und Laden fast aller Objekte benötigen:

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)

Diese Funktionen setzen voraus, dass sich objin Ihrem aktuellen Arbeitsverzeichnis ein Ordner befindet, in dem die Objekte gespeichert werden.

Beachten Sie, dass dies pickle.HIGHEST_PROTOCOLein Binärformat ist, das nicht immer praktisch sein kann, aber gut für die Leistung ist. Das Protokoll 0ist ein Textformat.

Um Python-Sammlungen zu speichern, gibt es das Shelve- Modul.

Zah
quelle
1
save_objscheint zu erfordern, dass die Datei obj/'+ name + '.pklbereits vorhanden ist. Ich habe ein Wörterbuch mit dem Namen erstellt Q, es ausgefüllt und den Aufruf getätigt. save_obj(Q, "Qtable")Ich habe eine Fehlermeldung erhalten: FileNotFoundError: [Errno 2] No such file or directory: 'obj/Qtable.pkl'Wie erstellt man die Datei überhaupt, bevor ich darauf schreibe?
Zahnstocher Anemone
1
@ToothpickAnemone verwenden wb+, um Datei zu erstellen, dh:with open('obj/'+ name + '.pkl', 'wb+')
andrey.s
1
@ andrey.s: Ich denke nicht, dass das, was Sie sagen, einen Unterschied machen wird, weil es das Problem nicht anspricht.
Martineau
1
@Toothpick Anemone: Das Hinzufügen von a +zum Modus hat keine Auswirkungen auf Ihr Problem (andrey.s ist falsch). Ihr Problem scheint auf ein oder zwei Dinge zurückzuführen zu sein. Damit das save_obj()in dieser Antwort funktioniert, "obj"muss bereits ein Unterverzeichnis mit dem Namen vorhanden sein, da open()es nicht automatisch erstellt wird. Zweitens ist das erste Argument save_obj()das zu speichernde Python-Objekt, nicht der Name des Unterverzeichnisses (obwohl nicht ganz klar ist, was Sie mit dem Qim Beispielaufruf gemeint haben save_obj(Q, "Qtable")). Sie können ein Verzeichnis erstellen, wenn es noch nicht mit beendet wurde os.mkdir().
Martineau
168

Pickle ist wahrscheinlich die beste Option, aber falls sich jemand fragt, wie ein Wörterbuch mit NumPy gespeichert und in eine Datei geladen werden kann:

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"

Zu Ihrer Information : NPY-Datei-Viewer

Franck Dernoncourt
quelle
4
Wofür ist das .item ()?
Gulzar
Warum ist diese Antwort weniger positiv bewertet als @Zahs "Pickle" -Antwort? Raumkomplexer?
Nathan
1
@frank Möglichkeit, da pickle Teil der Standardbibliothek von Python ist, in der numpy ein unabhängiges Projekt ist.
Maxim Veksler
2
@ Gulzar von dem, was ich nachgeschlagen habe, np.load gibt ein ndarray zurück (macht eine Enthüllung type(read_dictionary)so) und .item () konvertiert dieses Element im Grunde in ein Python-Skalar-Objekt, das ein Wörterbuch ist, wie hier
abhyudayasrinet
2
@Shai hast du das numpy Paket installiert ...?
Eben
26

Wir können das jsonModul auch verwenden, wenn Wörterbücher oder andere Daten problemlos dem JSON- Format zugeordnet werden können.

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

Diese Lösung bietet viele Vorteile , z. B. funktioniert Python 2.x und Python 3.x in unveränderter Form. Darüber hinaus können im JSON- Format gespeicherte Daten problemlos zwischen vielen verschiedenen Plattformen oder Programmen übertragen werden . Diese Daten sind auch für Menschen lesbar .

simhumileco
quelle
Guter Ansatz, aber ich denke nicht, dass es sicher ist, opendirekt anstelle eines von erstellten Kontexts zu verwenden with. Gibt es eine Garantie, wird das Dateihandle geschlossen, wenn dies json.dumpfehlschlägt?
Dr_Zaszuś
18

Ich bin nicht sicher, was Ihre erste Frage ist, aber wenn Sie ein Wörterbuch in einer Datei speichern möchten, sollten Sie die jsonBibliothek verwenden. Schlagen Sie die Dokumentation der Lasten und Put-Funktionen nach.

John
quelle
Warum json? Es ist noch einfacher, das Python-Wörterbuch mit "repr"
mguijarr
5
@mguijarr, aber es zurück zu analysieren ist nicht so einfach. Außerdem kann json einfach von Hand bearbeitet und in jedes andere Programm importiert werden.
Kalhartt
1
Ich mag Johns Vorschlag - siehe diesen Beitrag für ein gutes und einfaches Beispiel stackoverflow.com/a/11027021/765827
jacanterbury
9

Diktat speichern und in Datei laden:

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
quelle
3

Für ein Wörterbuch mit Zeichenfolgen wie der, mit der Sie es zu tun haben, können nur die in Python integrierten Textverarbeitungsfunktionen verwendet werden.

(Beachten Sie, dass dies nicht funktionieren würde, wenn die Werte etwas anderes sind.)

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
quelle
Dies funktioniert nicht in Wörterbüchern: file.write (':'. Join ([id] + values.split (':')) + '\ n') AttributeError: 'dict' Objekt hat kein Attribut 'split'
Shai Alon
@ShaiAlon: Nicht bei allen, nein. Es funktioniert definitiv mit denen, deren Werte Zeichenfolgen sind (die eine split()Methode haben) - was das Thema dieser Frage ist. Es hört sich so an, als würden Sie versuchen, es in einem Wörterbuch mit Wörterbüchern zu verwenden, also nein, es würde mit diesen nicht funktionieren. Ich schätze auch Abstimmungen von Leuten nicht, weil sie die Frage (und damit den Kontext der Antworten) nicht wirklich verstehen. Ich werde meine Antwort aktualisieren, um sie zu verwenden, wenn sie angemessen wäre. Bitte machen Sie Ihre Abwertung rückgängig.
Martineau
3

Ich würde vorschlagen, Ihre Daten im JSON-Format anstelle des Pickle-Formats zu speichern, da die JSON-Dateien für Menschen lesbar sind, was das Debuggen erleichtert, da Ihre Daten klein sind. JSON-Dateien werden auch von anderen Programmen zum Lesen und Schreiben von Daten verwendet. Sie können mehr darüber lesen Sie hier

Sie müssen das JSON-Modul installieren. Dies können Sie mit pip tun:

pip install json


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

Dadurch wird eine JSON-Datei mit dem Namen myfile erstellt.

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

Dadurch werden die myfile.json-Daten in einem Datenobjekt gelesen und gespeichert.

Kavin Sabharwal
quelle
2

Wenn Sie das Wörterbuch nicht wirklich behalten möchten, ist es meiner Meinung nach die beste Lösung, das csvPython-Modul zum Lesen der Datei zu verwenden. Dann erhalten Sie Datenzeilen und können ändern member_phoneoder was auch immer Sie wollen; Schließlich können Sie das csvModul erneut verwenden, um die Datei im selben Format zu speichern, in dem Sie sie geöffnet haben.

Code zum Lesen:

import csv

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

Code zum Schreiben:

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

Natürlich müssen Sie Ihre change()Funktion anpassen :

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
quelle
was ist gemeint mitOf course, you need to adapt your change() function:
kRazzy R
1
In der Frage wurde a dict verwendet, während CSV eher wie eine Liste
funktioniert
1

Ich habe es nicht geplant, aber ich wette, h5 ist schneller als Gurke; Die Dateigröße mit Komprimierung ist mit ziemlicher Sicherheit kleiner.

import deepdish as dd
dd.io.save(filename, {'dict1': dict1, 'dict2': dict2}, compression=('blosc', 9))
Worte dafür
quelle
-2

Schnelle und schmutzige Lösung: Konvertieren Sie das Diktat in einen String und speichern Sie es in einer Datei, z.

#dict could be anything:

savedict = open('savedict001.txt', 'w')
savedict.write(str(dict))
savedict.close()
Patrick Stacey
quelle
Das Konvertieren von Diktat in str und das Speichern funktioniert nicht, insbesondere wenn Sie pd.Series oder np.ndarray als Schlüssel in den Zeichenfolgen haben.
Arpan Srivastava