Almacenamiento de diccionarios Python

198

Estoy acostumbrado a ingresar y sacar datos de Python usando archivos .csv, pero hay desafíos obvios para esto. ¿Algún consejo sobre formas simples de almacenar un diccionario (o conjuntos de diccionarios) en un archivo json o pck? Por ejemplo:

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

Me gustaría saber cómo guardar esto y luego cómo volver a cargarlo.

Miguel
fuente
8
¿Ha leído la documentación de los módulos estándar json o pickle ?
Greg Hewgill

Respuestas:

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)

Consulte la documentación del módulo pickle para obtener información adicional sobre el protocolargumento.

Carga de pepinillos :

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

JSON guardar:

import json

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

Proporcione argumentos adicionales como sort_keyso indentpara obtener un resultado bonito. El argumento sort_keys ordenará las claves alfabéticamente y la sangría sangrará su estructura de datos con indent=Nespacios.

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

Carga JSON :

with open('data.json', 'r') as fp:
    data = json.load(fp)
Marty
fuente
44
JSON hace diccionarios de forma nativa (aunque obviamente no se comportan exactamente como un diccionario de Python mientras está en la memoria, para propósitos de persistencia, son idénticos). De hecho, la unidad fundamental en json es el "Objeto", que se define como {<string>: <value>}. ¿Parecer familiar? El módulo json en la biblioteca estándar admite todos los tipos nativos de Python y puede ampliarse fácilmente con un conocimiento mínimo de json para admitir clases definidas por el usuario. La página de inicio de JSON define completamente el idioma en poco más de 3 páginas impresas, por lo que es fácil de absorber / digerir rápidamente.
Jonathanb
1
También vale la pena conocer el tercer argumento pickle.dump. Si el archivo no necesita ser legible por humanos, puede acelerar mucho las cosas.
Steve Jessop
11
Si agrega sort_keys y sangría argumentos a la llamada de volcado obtendrá un resultado mucho más bonito. por ejemplo: json.dump(data, fp, sort_keys=True, indent=4). Más información se puede encontrar aquí
juliusmh
1
Probablemente deberías usarpickle.dump(data, fp, protocol=pickle.HIGHEST_PROTOCOL)
Martin Thoma
1
Para python 3, useimport pickle
danger89
35

Ejemplo mínimo, escribir directamente en un archivo:

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

o abrir / cerrar de forma segura:

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

Si desea guardarlo en una cadena en lugar de un archivo:

import json
json_str = json.dumps(data)
data = json.loads(json_str)
agf
fuente
5

Para escribir en un archivo:

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

Para leer de un archivo:

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

myfile es el objeto de archivo para el archivo en el que almacenó el dict.

Rafe Kettler
fuente
¿Es usted lo que tiene JSON que toma los archivos como argumentos y los escribe directamente?
json.dump(myfile)yjson.load(myfile)
Niklas R
5

Si busca la serialización pero no necesita los datos en otros programas, le recomiendo el shelvemódulo. Piense en ello como un diccionario 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()
gddc
fuente
2
Si desea almacenar un dict completo, o cargar un dict completo, jsones más conveniente. shelvesolo es mejor para acceder a una clave a la vez.
agf
3

Si desea una alternativa a pickleo json, puede usar 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, si hubiera utilizado serialized=True, el diccionario se habría escrito memo.pklcomo un diccionario en vinagre en lugar de con texto claro.

Puedes llegar kleptoaquí: https://github.com/uqfoundation/klepto

dillProbablemente sea una mejor opción para conservar en vinagre que en picklesí mismo, ya que dillpuede serializar casi cualquier cosa en Python. kleptoTambién puede usar dill.

Puedes llegar dillaquí: https://github.com/uqfoundation/dill

El mumbo-jumbo adicional en las primeras líneas se debe a que kleptose puede configurar para almacenar diccionarios en un archivo, en un contexto de directorio o en una base de datos SQL. La API es la misma para lo que elija como archivo de back-end. Le proporciona un diccionario "archivable" con el que puede usar loade dumpinteractuar con el archivo.

Mike McKerns
fuente
3

Este es un tema antiguo, pero para completar, debemos incluir ConfigParser y configparser que forman parte de la biblioteca estándar en Python 2 y 3, respectivamente. Este módulo lee y escribe en un archivo config / ini y (al menos en Python 3) se comporta de muchas maneras como un diccionario. Tiene el beneficio adicional de que puede almacenar múltiples diccionarios en secciones separadas de su archivo config / ini y recuperarlos. ¡Dulce!

Python 2.7.x ejemplo.

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 ejemplo.

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)

salida de consola

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

contenido de config.ini

[dict1]
key2 = keyinfo2
key1 = keyinfo

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

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

Si guarda en un archivo json, la mejor y más fácil forma de hacerlo es:

import json
with open("file.json", "wb") as f:
    f.write(json.dumps(dict).encode("utf-8"))
Adam Liu
fuente
¿Por qué es esto más fácil que json.dump( )como se describe en la otra respuesta?
baxx
0

mi caso de uso fue guardar múltiples objetos json en un archivo y la respuesta de marty me ayudó un poco. Pero para responder a mi caso de uso, la respuesta no estaba completa, ya que sobrescribiría los datos antiguos cada vez que se guarda una nueva entrada.

Para guardar múltiples entradas en un archivo, uno debe verificar el contenido anterior (es decir, leer antes de escribir). Un archivo típico que contiene datos json tendrá una listo una objectraíz. Así que consideré que mi archivo json siempre tiene una list of objectsy cada vez que agrego datos a ella, simplemente cargo la lista primero, agrego mis nuevos datos y la vuelvo a una instancia de archivo de solo escritura ( 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"

el nuevo archivo json se verá así:

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

NOTA: Es esencial tener un archivo con el nombre file.jsoncon el []que los datos iniciales de este enfoque para el trabajo

PD: no está relacionado con la pregunta original, pero este enfoque también podría mejorarse más si primero verificamos si nuestra entrada ya existe (basada en 1 / claves múltiples) y solo luego agregamos y guardamos los datos. Avíseme si alguien necesita ese cheque, agregaré a la respuesta

ansh sachdeva
fuente