Memorizzazione dei dizionari Python


198

Sono abituato a inserire e estrarre dati da Python usando file .csv, ma ci sono ovvie sfide a questo. Qualche consiglio su come semplificare la memorizzazione di un dizionario (o set di dizionari) in un file json o pck? Per esempio:

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

Vorrei sapere sia come salvarlo, sia come ricaricarlo.


8
Hai letto la documentazione per i moduli json o pickle standard?
Greg Hewgill,

Risposte:


443

Pickle save:

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)

Vedere la documentazione del modulo pickle per ulteriori informazioni protocolsull'argomento.

Carico sottaceto :

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

Risparmio JSON :

import json

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

Fornisci argomenti extra come sort_keyso indentper ottenere un bel risultato. L'argomento sort_keys ordinerà le chiavi in ​​ordine alfabetico e il rientro indenterà la struttura dei dati con indent=Nspazi.

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

Caricamento JSON :

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

4
JSON fa i dizionari in modo nativo (anche se ovviamente non si comportano esattamente come un dizionario Python mentre sono in memoria, per motivi di persistenza, sono identici). In effetti, l'unità base in json è "Object", che è definito come {<string>: <value>}. Ti sembra familiare? Il modulo json nella libreria standard supporta tutti i tipi nativi di Python e può essere facilmente esteso con una conoscenza minima di json per supportare le classi definite dall'utente. La homepage di JSON definisce completamente la lingua in poco più di 3 pagine stampate, quindi è facile da assorbire / digerire rapidamente.
Jonathanb,

1
Vale la pena conoscere anche il terzo argomento pickle.dump. Se il file non ha bisogno di essere leggibile dall'uomo, può velocizzare molto le cose.
Steve Jessop,

11
Se si aggiungono sort_keys e argomenti indent alla chiamata di dump si ottiene un risultato molto più bello. ad es json.dump(data, fp, sort_keys=True, indent=4). : . Maggiori informazioni possono essere trovate qui
Juliusmh

1
Probabilmente dovresti usarepickle.dump(data, fp, protocol=pickle.HIGHEST_PROTOCOL)
Martin Thoma il

1
Per python 3, usaimport pickle
danger89

35

Esempio minimo, scrivendo direttamente in un file:

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

o apertura / chiusura sicura:

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

Se vuoi salvarlo in una stringa anziché in un file:

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


5

Per scrivere in un file:

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

Per leggere da un file:

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

myfile è l'oggetto file per il file in cui è stato memorizzato il dict.


sei a conoscenza di Json che prende i file come argomenti e li scrive direttamente?

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

5

Se stai cercando la serializzazione ma non avrai bisogno dei dati in altri programmi, consiglio vivamente il shelvemodulo. Pensalo come un dizionario persistente.

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
Se si desidera archiviare un intero dict o caricare un intero dict, jsonè più conveniente. shelveè migliore solo per accedere a una chiave alla volta.
agf

3

Se si desidera un'alternativa a pickleo json, è possibile utilizzare 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}

Con klepto, se lo avessi usato serialized=True, il dizionario sarebbe stato scritto memo.pklcome un dizionario sottaceto anziché con testo in chiaro.

Puoi arrivare kleptoqui: https://github.com/uqfoundation/klepto

dillè probabilmente una scelta migliore per il decapaggio rispetto a picklese stesso, poiché dillpuò serializzare quasi tutto in Python. kleptoanche può usare dill.

Puoi arrivare dillqui: https://github.com/uqfoundation/dill

I mumbo-jumbo aggiuntivi nelle prime poche righe sono perché kleptopossono essere configurati per memorizzare dizionari in un file, in un contesto di directory o in un database SQL. L'API è la stessa per qualunque cosa tu scelga come archivio back-end. Ti dà un dizionario "archiviabile" con il quale puoi usare loade dumpinteragire con l'archivio.


3

Questo è un vecchio argomento, ma per completezza, dovremmo includere ConfigParser e configparser che fanno parte della libreria standard in Python 2 e 3, rispettivamente. Questo modulo legge e scrive in un file config / ini e (almeno in Python 3) si comporta in molti modi come un dizionario. Ha il vantaggio aggiuntivo di poter memorizzare più dizionari in sezioni separate del file config / ini e richiamarli. Dolce!

Esempio di Python 2.7.x.

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)

Esempio di Python 3.X.

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)

uscita console

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

contenuto di config.ini

[dict1]
key2 = keyinfo2
key1 = keyinfo

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

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

1

Se si salva in un file json, il modo migliore e più semplice per farlo è:

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

perché è più facile di json.dump( )quanto indicato nell'altra risposta?
baxx,

0

il mio caso d'uso era di salvare più oggetti json in un file e la risposta di Marty mi ha aiutato in qualche modo. Ma per servire il mio caso d'uso la risposta non era completa in quanto avrebbe sovrascritto i vecchi dati ogni volta che veniva salvata una nuova voce.

Per salvare più voci in un file, è necessario verificare il vecchio contenuto (ovvero leggere prima di scrivere). Un file tipico contenente dati json avrà listo objectcome root. Quindi ho considerato che il mio file json ha sempre un list of objectse ogni volta che aggiungo dati ad esso, carico semplicemente l'elenco prima, aggiungo i miei nuovi dati in esso e li scarico in un'istanza di file scrivibile ( 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"

il nuovo file json sarà simile al seguente:

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

NOTA: è essenziale disporre di un file file.jsoncon nome []come dati iniziali affinché questo approccio funzioni

PS: non correlato alla domanda originale, ma questo approccio potrebbe anche essere ulteriormente migliorato controllando prima se la nostra voce esiste già (basata su 1 / più chiavi) e solo successivamente aggiungi e salva i dati. Fammi sapere se qualcuno ha bisogno di quel controllo, aggiungerò alla risposta

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.