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.

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)

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.


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) 

14

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


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.


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

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) 

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}

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]

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

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.