Speichern von Python-Wörterbüchern


198

Ich bin es gewohnt, Daten mithilfe von CSV-Dateien in Python ein- und auszublenden, aber dies birgt offensichtliche Herausforderungen. Irgendwelche Ratschläge zu einfachen Möglichkeiten, ein Wörterbuch (oder Wörterbuchsätze) in einer JSON- oder Pck-Datei zu speichern? Beispielsweise:

data = {}
data ['key1'] = "keyinfo"
data ['key2'] = "keyinfo2"

Ich würde gerne wissen, wie man dies speichert und wie man es dann wieder einlädt.


8
Haben Sie die Dokumentation zu den Standardmodulen json oder pickle gelesen ?
Greg Hewgill

Antworten:


443

Pickle speichern:

try:
    import cPickle as pickle
except ImportError:  # python 3.x
    import pickle

with open('data.p', 'wb') as fp:
    pickle.dump(data, fp, protocol=pickle.HIGHEST_PROTOCOL)

Weitere Informationen zum Argument finden Sie in der Dokumentation zum Pickle-Modulprotocol .

Essiggurkenladung :

with open('data.p', 'rb') as fp:
    data = pickle.load(fp)

JSON speichern:

import json

with open('data.json', 'w') as fp:
    json.dump(data, fp)

Geben Sie zusätzliche Argumente wie sort_keysoder indentan, um ein hübsches Ergebnis zu erzielen. Das Argument sort_keys sortiert die Schlüssel alphabetisch und durch Einrücken wird Ihre Datenstruktur mit indent=NLeerzeichen eingerückt .

json.dump(data, fp, sort_keys=True, indent=4)

JSON laden:

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

4
JSON erstellt Wörterbücher nativ (obwohl sie sich offensichtlich nicht genau wie ein Python-Wörterbuch verhalten, während sie sich im Speicher befinden, sind sie aus Gründen der Persistenz identisch). Tatsächlich ist die Grundeinheit in json das "Objekt", das als {<string>: <value>} definiert ist. Ähnlich aussehend? Das json-Modul in der Standardbibliothek unterstützt jeden nativen Python-Typ und kann mit minimalen Kenntnissen von json problemlos erweitert werden, um benutzerdefinierte Klassen zu unterstützen. Die JSON-Homepage definiert die Sprache vollständig in etwas mehr als 3 gedruckten Seiten, sodass sie schnell aufgenommen / verdaut werden kann.
Jonathanb

1
Es lohnt sich auch, über das dritte Argument Bescheid zu wissen pickle.dump. Wenn die Datei nicht für Menschen lesbar sein muss, kann dies die Dinge erheblich beschleunigen.
Steve Jessop

11
Wenn Sie fügen sort_keys und indent Argumente , um den Dump Anruf erhalten Sie ein viel schöneres Ergebnis. zB : json.dump(data, fp, sort_keys=True, indent=4). Weitere Informationen finden Sie hier
Juliusmh

1
Sie sollten wahrscheinlich verwendenpickle.dump(data, fp, protocol=pickle.HIGHEST_PROTOCOL)
Martin Thoma

1
Verwenden import pickle
Sie

35

Minimales Beispiel, direkt in eine Datei schreiben:

import json
json.dump(data, open(filename, 'wb'))
data = json.load(open(filename))

oder sicher öffnen / schließen:

import json
with open(filename, 'wb') as outfile:
    json.dump(data, outfile)
with open(filename) as infile:
    data = json.load(infile)

Wenn Sie es in einer Zeichenfolge anstelle einer Datei speichern möchten:

import json
json_str = json.dumps(data)
data = json.loads(json_str)


5

So schreiben Sie in eine Datei:

import json
myfile.write(json.dumps(mydict))

So lesen Sie aus einer Datei:

import json
mydict = json.loads(myfile.read())

myfile ist das Dateiobjekt für die Datei, in der Sie das Diktat gespeichert haben.


Sie sind der Meinung, dass json Dateien als Argumente nimmt und direkt darauf schreibt?

json.dump(myfile)undjson.load(myfile)
Niklas R

5

Wenn Sie nach der Serialisierung sind, aber die Daten in anderen Programmen nicht benötigen, empfehle ich das shelveModul dringend . Betrachten Sie es als ein beständiges Wörterbuch.

myData = shelve.open('/path/to/file')

# check for values.
keyVar in myData

# set values
myData[anotherKey] = someValue

# save the data for future use.
myData.close()

2
Wenn Sie ein ganzes Diktat speichern oder ein ganzes Diktat laden möchten, jsonist dies bequemer. shelveist nur besser für den Zugriff auf jeweils einen Schlüssel.
Agf

3

Wenn Sie eine Alternative zu pickleoder möchten json, können Sie verwenden klepto.

>>> init = {'y': 2, 'x': 1, 'z': 3}
>>> import klepto
>>> cache = klepto.archives.file_archive('memo', init, serialized=False)
>>> cache        
{'y': 2, 'x': 1, 'z': 3}
>>>
>>> # dump dictionary to the file 'memo.py'
>>> cache.dump() 
>>> 
>>> # import from 'memo.py'
>>> from memo import memo
>>> print memo
{'y': 2, 'x': 1, 'z': 3}

Mit klepto, wenn Sie verwendet hätten serialized=True, wäre das Wörterbuch memo.pklals eingelegtes Wörterbuch anstatt mit klarem Text geschrieben worden.

Sie erhalten kleptohier: https://github.com/uqfoundation/klepto

dillist wahrscheinlich eine bessere Wahl zum Beizen als pickleselbst, da dillfast alles in Python serialisiert werden kann. kleptokann auch verwenden dill.

Sie erhalten dillhier: https://github.com/uqfoundation/dill

Das zusätzliche Hokuspokus in den ersten Zeilen liegt daran klepto es so konfiguriert kann, dass Wörterbücher in einer Datei, in einem Verzeichniskontext oder in einer SQL-Datenbank gespeichert werden. Die API ist für alles, was Sie als Backend-Archiv auswählen, dieselbe. Sie erhalten ein "archivierbares" Wörterbuch, mit dem Sie das Archiv verwenden loadund dumpmit ihm interagieren können.


3

Dies ist ein altes Thema, aber der Vollständigkeit halber sollten wir ConfigParser und configparser einschließen, die Teil der Standardbibliothek in Python 2 bzw. 3 sind. Dieses Modul liest und schreibt in eine config / ini-Datei und verhält sich (zumindest in Python 3) in vielerlei Hinsicht wie ein Wörterbuch. Es hat den zusätzlichen Vorteil, dass Sie mehrere Wörterbücher in separaten Abschnitten Ihrer config / ini-Datei speichern und abrufen können. Süss!

Python 2.7.x Beispiel.

import ConfigParser

config = ConfigParser.ConfigParser()

dict1 = {'key1':'keyinfo', 'key2':'keyinfo2'}
dict2 = {'k1':'hot', 'k2':'cross', 'k3':'buns'}
dict3 = {'x':1, 'y':2, 'z':3}

# make each dictionary a separate section in config
config.add_section('dict1')
for key in dict1.keys():
    config.set('dict1', key, dict1[key])

config.add_section('dict2')
for key in dict2.keys():
    config.set('dict2', key, dict2[key])

config.add_section('dict3')
for key in dict3.keys():
    config.set('dict3', key, dict3[key])

# save config to file
f = open('config.ini', 'w')
config.write(f)
f.close()

# read config from file
config2 = ConfigParser.ConfigParser()
config2.read('config.ini')

dictA = {}
for item in config2.items('dict1'):
    dictA[item[0]] = item[1]

dictB = {}
for item in config2.items('dict2'):
    dictB[item[0]] = item[1]

dictC = {}
for item in config2.items('dict3'):
    dictC[item[0]] = item[1]

print(dictA)
print(dictB)
print(dictC)

Python 3.X Beispiel.

import configparser

config = configparser.ConfigParser()

dict1 = {'key1':'keyinfo', 'key2':'keyinfo2'}
dict2 = {'k1':'hot', 'k2':'cross', 'k3':'buns'}
dict3 = {'x':1, 'y':2, 'z':3}

# make each dictionary a separate section in config
config['dict1'] = dict1
config['dict2'] = dict2
config['dict3'] = dict3

# save config to file
f = open('config.ini', 'w')
config.write(f)
f.close()

# read config from file
config2 = configparser.ConfigParser()
config2.read('config.ini')

# ConfigParser objects are a lot like dictionaries, but if you really
# want a dictionary you can ask it to convert a section to a dictionary
dictA = dict(config2['dict1'] )
dictB = dict(config2['dict2'] )
dictC = dict(config2['dict3'])

print(dictA)
print(dictB)
print(dictC)

Konsolenausgabe

{'key2': 'keyinfo2', 'key1': 'keyinfo'}
{'k1': 'hot', 'k2': 'cross', 'k3': 'buns'}
{'z': '3', 'y': '2', 'x': '1'}

Inhalt der config.ini

[dict1]
key2 = keyinfo2
key1 = keyinfo

[dict2]
k1 = hot
k2 = cross
k3 = buns

[dict3]
z = 3
y = 2
x = 1

1

Wenn Sie in einer JSON-Datei speichern, ist dies am besten und einfachsten:

import json
with open("file.json", "wb") as f:
    f.write(json.dumps(dict).encode("utf-8"))

Warum ist das einfacher als json.dump( )in der anderen Antwort beschrieben?
Baxx

0

Mein Anwendungsfall war das Speichern mehrerer JSON-Objekte in einer Datei, und Martys Antwort half mir etwas. Um meinem Anwendungsfall gerecht zu werden, war die Antwort jedoch nicht vollständig, da die alten Daten jedes Mal überschrieben würden, wenn ein neuer Eintrag gespeichert wird.

Um mehrere Einträge in einer Datei zu speichern, muss nach dem alten Inhalt gesucht werden (dh vor dem Schreiben lesen). Eine typische Datei mit JSON-Daten hat entweder ein listoder ein objectals root. Daher habe ich berücksichtigt, dass meine JSON-Datei immer eine enthält. list of objectsJedes Mal, wenn ich Daten hinzufüge, lade ich einfach zuerst die Liste, füge meine neuen Daten hinzu und speichere sie wieder in eine nur beschreibbare Instanz von file ( w):

def saveJson(url,sc): #this function writes the 2 values to file
    newdata = {'url':url,'sc':sc}
    json_path = "db/file.json"

    old_list= []
    with open(json_path) as myfile:  #read the contents first
        old_list = json.load(myfile)
    old_list.append(newdata)

    with open(json_path,"w") as myfile:  #overwrite the whole content
        json.dump(old_list,myfile,sort_keys=True,indent=4)

    return "sucess"

Die neue JSON-Datei sieht ungefähr so ​​aus:

[
    {
        "sc": "a11",
        "url": "www.google.com"
    },
    {
        "sc": "a12",
        "url": "www.google.com"
    },
    {
        "sc": "a13",
        "url": "www.google.com"
    }
]

HINWEIS: Es ist wichtig, eine Datei file.jsonmit []den Anfangsdaten zu haben, damit dieser Ansatz funktioniert

PS: Nicht im Zusammenhang mit der ursprünglichen Frage, aber dieser Ansatz könnte auch weiter verbessert werden, indem zunächst geprüft wird, ob unser Eintrag bereits vorhanden ist (basierend auf 1 / mehreren Schlüsseln), und erst dann die Daten angehängt und gespeichert werden. Lassen Sie mich wissen, wenn jemand diesen Scheck benötigt, ich werde die Antwort ergänzen

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.