¿Una forma elegante de guardar el diccionario permanentemente con Python?

Actualmente, es muy costoso analizar un archivo, que genera un diccionario de ~ 400 claves, pares de valores, que rara vez se actualizan. Anteriormente tenía una función que analizaba el archivo, lo escribía en un archivo de texto en la syntax del diccionario (es decir, dict = {'Adam': 'Room 430', 'Bob': 'Room 404'} ), etc., y lo copiaba y lo pegaba en otra función cuyo único propósito era devolver ese diccionario analizado.

Por lo tanto, en cada archivo en el que usaría ese diccionario, importaría esa función y la asignaría a una variable, que ahora es ese diccionario. ¿Se pregunta si hay una forma más elegante de hacer esto, que no implique copiar y pegar explícitamente el código? El uso de una base de datos parece innecesario, y el archivo de texto me dio la ventaja de ver si el análisis se realizó correctamente antes de agregarlo a la función. Pero estoy abierto a sugerencias.

¿Por qué no volcarlo en un archivo JSON y luego cargarlo desde allí donde lo necesite?

 import json with open('my_dict.json', 'w') as f: json.dump(my_dict, f) # elsewhere... with open('my_dict.json') as f: my_dict = json.load(f) 

La carga desde JSON es bastante eficiente.

Otra opción sería utilizar pickle , pero a diferencia de JSON, los archivos que genera no son legibles por humanos, por lo que se pierde la verificación visual que le gustó de su método anterior.

¿Por qué meterse con todos estos métodos de serialización? Ya está escrito en un archivo como un dict de Python (aunque con el desafortunado nombre ‘dict’). Cambie su progtwig para escribir los datos con un mejor nombre de variable, tal vez “datos” o “catálogo”, y guarde el archivo como un archivo Python, por ejemplo, data.py. Luego, solo puede importar los datos directamente en tiempo de ejecución sin copiar / pegar de forma torpe o JSON / shelve / etc. análisis

 from data import catalog 

JSON es probablemente el camino correcto en muchos casos; pero podría haber una alternativa. Parece que sus claves y sus valores son siempre cadenas, ¿es así? Podría considerar usar dbm / anydbm . Estas son “bases de datos” pero actúan casi exactamente como diccionarios. Son excelentes para la persistencia de datos baratos.

 >>> import anydbm >>> dict_of_strings = anydbm.open('data', 'c') >>> dict_of_strings['foo'] = 'bar' >>> dict_of_strings.close() >>> dict_of_strings = anydbm.open('data') >>> dict_of_strings['foo'] 'bar' 

Si las claves son todas las cadenas, puede utilizar el módulo de almacenamiento

Un estante es un objeto persistente, similar a un diccionario. La diferencia con las bases de datos “dbm” es que los valores (¡no las claves!) En un estante pueden ser objetos Python esencialmente arbitrarios, cualquier cosa que pueda manejar el módulo pickle. Esto incluye la mayoría de las instancias de clase, tipos de datos recursivos y objetos que contienen muchos subobjetos compartidos. Las llaves son cuerdas ordinarias.

json sería una buena opción si necesita utilizar los datos de otros idiomas

Si la eficiencia del almacenamiento es importante, use Pickle o CPickle (para boost el rendimiento de la ejecución). Como señaló Amber, también puedes descargar / cargar a través de Json. Será legible para los humanos, pero requiere más disco.

Le sugiero que considere usar el módulo de shelve ya que su estructura de datos es un mapeo. Esa fue mi respuesta a una pregunta similar titulada Si quiero crear una base de datos personalizada, ¿cómo podría hacerlo? También hay un poco de código de ejemplo en otra de mis respuestas que promueve su uso para la pregunta ¿Cómo obtener una base de datos de objetos?

ActiveState tiene una receta PersistentDict altamente calificada que admite formatos de archivo de salida csv, json y pickle. Es bastante rápido, ya que los tres formatos se implementan en C (aunque la receta en sí es Python pura), por lo que el hecho de que lea todo el archivo en la memoria cuando se abra puede ser aceptable.

en la dirección JSON también hay algo que se llama simpleJSON. La primera vez que usé json in python, la biblioteca json no funcionó para mí / no pude resolverlo. simpleJSON fue … más fácil de usar

La serialización JSON (o YAML, o lo que sea) es probablemente mejor, pero si ya está escribiendo el diccionario en un archivo de texto con syntax de python, completo con un enlace de nombre variable, podría escribirlo en un archivo .py en su lugar. Entonces ese archivo de Python sería importable y utilizable como es. No es necesario el enfoque de “función que devuelve un diccionario”, ya que puede usarlo directamente como un archivo global en ese archivo. p.ej

 # generated.py please_dont_use_dict_as_a_variable_name = {'Adam': 'Room 430', 'Bob': 'Room 404'} 

más bien que:

 # manually_copied.py def get_dict(): return {'Adam': 'Room 430', 'Bob': 'Room 404'} 

La única diferencia es que manually_copied.get_dict te da una copia nueva del diccionario cada vez, mientras que generated.please_dont_use_dict_as_a_variable_name [1] es un único objeto compartido. Esto puede importar si está modificando el diccionario en su progtwig después de recuperarlo, pero siempre puede usar copy.copy o copy.deepcopy para crear una nueva copia si necesita modificar uno independientemente de los otros.


[1] dict , list , str , int , map , etc. generalmente se ven como nombres de variables incorrectos. La razón es que ya están definidas como integradas y se usan muy comúnmente. Por lo tanto, si le da a un nombre así algo, al menos causará disonancia cognitiva para las personas que leen su código (incluido usted después de haber estado ausente por un tiempo) ya que tienen que tener en cuenta que “el dict no lo hace”. T significa lo que normalmente hace aquí “. También es bastante probable que en algún momento se produzca un informe de error enfurecedor para resolver que los objetos dict no son invocables (o algo así), porque algún fragmento de código está intentando usar el dict tipo , pero está obteniendo el diccionario objeto que enlaza con el nombre dict lugar.