Convierta un pitón dict en una cadena y viceversa

275

Estoy escribiendo un programa que almacena datos en un objeto de diccionario, pero estos datos deben guardarse en algún momento durante la ejecución del programa y cargarse nuevamente en el objeto de diccionario cuando el programa se ejecute nuevamente. ¿Cómo convertiría un objeto de diccionario en una cadena que se pueda escribir en un archivo y volver a cargar en un objeto de diccionario? Con suerte, esto admitirá diccionarios que contengan diccionarios.

AJ00200
fuente

Respuestas:

274

El módulo json es una buena solución aquí. Tiene las ventajas sobre pickle de que solo produce salida de texto sin formato, y es multiplataforma y versión cruzada.

import json
json.dumps(dict)
Aleros Tyler
fuente
2
Voy a echar un vistazo a este módulo también. Tanto json como pickle parecen bastante fáciles de usar, por lo que se reducirá a cosas como el soporte multiplataforma. Gracias
AJ00200
55
Pickle tiende a ser visto como algo obsoleto en este punto. Siempre uso json para cosas como esta. Ser (relativamente) legible para los humanos es una GRAN ventaja más la mayor parte del tiempo.
Tyler Eaves
30
Debe agregar un ejemplo simple para permitir que los usuarios vean cómo hacerlo.
Miguel Vazq
1
@ TylerEaves ¿Puede proporcionar un ejemplo de cómo se debe hacer?
Boban
1
: foreheadslap: no olvides lo import jsonque hice!
Jesse Chisholm
207

Si su diccionario no es demasiado grande, tal vez str + eval pueda hacer el trabajo:

dict1 = {'one':1, 'two':2, 'three': {'three.1': 3.1, 'three.2': 3.2 }}
str1 = str(dict1)

dict2 = eval(str1)

print dict1==dict2

Puede usar ast.literal_eval en lugar de eval para obtener seguridad adicional si la fuente no es de confianza.

PabloG
fuente
13
Realmente no estoy preparado para lidiar con las posibles vulnerabilidades que esto podría introducir en el código. No sé qué problemas podría tener json o pickle, pero sé con certeza que evaluar sería peligroso en este caso.
AJ00200
55
@ AJ00200: ¿y la alternativa ast.literal_eval que mencioné? De la ayuda de Python: "Evalúe de forma segura un nodo de expresión o una cadena que contenga una expresión de Python. La cadena o nodo proporcionado solo puede consistir en las siguientes estructuras literales de Python: cadenas, números, tuplas, listas, dictos, booleanos y Ninguno. Esto se puede usar para evaluar de forma segura las cadenas que contienen expresiones de Python de fuentes no confiables sin la necesidad de analizar los valores uno mismo ".
PabloG
Parece útil, pero cuando anteriormente estaba usando SQLite para manejar estos datos y tenía más de 1500 entradas, por lo que es bastante grande y crece todo el tiempo.
AJ00200
164

Yo uso json:

import json

# convert to string
input = json.dumps({'id': id })

# load to dict
my_dict = json.loads(input) 
Eyal Ch
fuente
14

Use el picklemódulo para guardarlo en el disco y cargarlo más tarde.

ismail
fuente
2
@extraneon En realidad, es una respuesta a la pregunta. Lo convierte en una cadena en algún lugar y lo escribe en un archivo. No tengo que hacer la conversión real o escribir el archivo, ya que todo está encapsulado por pickle.
AJ00200
12

¿Por qué no utilizar incorporado de Python 3 ast función de biblioteca literal_eval . Es mejor usar literal_eval en lugar de eval

import ast
str_of_dict = "{'key1': 'key1value', 'key2': 'key2value'}"
ast.literal_eval(str_of_dict)

dará salida como diccionario real

{'key1': 'key1value', 'key2': 'key2value'}

Y si está pidiendo convertir un diccionario en una cadena , entonces, ¿qué tal usar el método str () de Python?

Supongamos que el diccionario es:

my_dict = {'key1': 'key1value', 'key2': 'key2value'}

Y esto se hará así:

str(my_dict)

Imprimirá:

"{'key1': 'key1value', 'key2': 'key2value'}"

Esto es lo fácil que te gusta.

FightWithCode
fuente
5

Si en chinses

import codecs
fout = codecs.open("xxx.json", "w", "utf-8")
dict_to_json = json.dumps({'text':"中文"},ensure_ascii=False,indent=2)
fout.write(dict_to_json + '\n')
beta
fuente
1
Esta sería una mejor respuesta si explicara cómo el código que proporcionó responde a la pregunta.
pppery
4

Convertir diccionario en JSON (cadena)

import json 

mydict = { "name" : "Don", 
          "surname" : "Mandol", 
          "age" : 43} 

result = json.dumps(mydict)

print(result[0:20])

te conseguirá:

{"nombre": "Don", "sur

Convertir cadena en diccionario

back_to_mydict = json.loads(result) 
Harvey
fuente
3

Creo que debería considerar el uso del shelvemódulo que proporciona objetos persistentes de tipo diccionario respaldados por archivos. Es fácil de usar en lugar de un diccionario "real" porque proporciona casi transparentemente a su programa algo que se puede usar como un diccionario, sin la necesidad de convertirlo explícitamente en una cadena y luego escribir en un archivo (o viceversa). viceversa).

La principal diferencia es necesitarlo inicialmente open()antes del primer uso y luego close()cuando termine (y posiblemente sync()hacerlo, dependiendo de la writebackopción que se esté usando). Cualquier archivo de "estantería" creado por los objetos puede contener diccionarios regulares como valores, lo que permite anidarlos lógicamente.

Aquí hay un ejemplo trivial:

import shelve

shelf = shelve.open('mydata')  # open for reading and writing, creating if nec
shelf.update({'one':1, 'two':2, 'three': {'three.1': 3.1, 'three.2': 3.2 }})
shelf.close()

shelf = shelve.open('mydata')
print shelf
shelf.close()

Salida:

{'three': {'three.1': 3.1, 'three.2': 3.2}, 'two': 2, 'one': 1}
Martineau
fuente
2

Si te importa la velocidad, usa ujson (UltraJSON), que tiene la misma API que json:

import ujson
ujson.dumps([{"key": "value"}, 81, True])
# '[{"key":"value"},81,true]'
ujson.loads("""[{"key": "value"}, 81, true]""")
# [{u'key': u'value'}, 81, True]
Tomasz Bartkowiak
fuente
1

Utilizo yaml para eso si necesita ser legible (ni JSON ni XML son eso en mi humilde opinión), o si la lectura no es necesaria, uso pickle.

Escribir

from pickle import dumps, loads
x = dict(a=1, b=2)
y = dict(c = x, z=3)
res = dumps(y)
open('/var/tmp/dump.txt', 'w').write(res)

Lee atrás

from pickle import dumps, loads
rev = loads(open('/var/tmp/dump.txt').read())
print rev
Gerard
fuente
Realmente deberías usar bflag al abrir el archivo aquí.
Piotr Dobrogost
1
Podría haber sido más explícito. Sin embargo, el valor dumps()predeterminado es el protocolo 0, que es un protocolo ASCII. Por eso 'rb'no es necesario en mi humilde opinión.
Gerard