web-dev-qa-db-fra.com

Manière élégante de stocker le dictionnaire de façon permanente avec Python?

Actuellement, l'analyse coûteuse d'un fichier, qui génère un dictionnaire de ~ 400 paires clé/valeur, qui est rarement mise à jour. Auparavant, une fonction analysait le fichier, l'écrivait dans un fichier texte en syntaxe de dictionnaire (c.-à-d. dict = {'Adam': 'Room 430', 'Bob': 'Room 404'}), etc., et la copiait et la collait dans une autre fonction dont le seul but était de renvoyer ce dictionnaire analysé.

Par conséquent, dans chaque fichier où j'utiliserais ce dictionnaire, j'importerais cette fonction et l'assignerais à une variable, qui est maintenant ce dictionnaire. Vous vous demandez s'il existe un moyen plus élégant de le faire, qui n'implique pas explicitement de copier/coller du code? L'utilisation d'une base de données semble inutile, et le fichier texte m'a permis de vérifier si l'analyse a été effectuée correctement avant de l'ajouter à la fonction. Mais je suis ouvert aux suggestions.

17
zhuyxn

Pourquoi ne pas le sauvegarder dans un fichier JSON, puis le charger à partir de là où vous en avez besoin?

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)

Le chargement depuis JSON est assez efficace.

Une autre option serait d’utiliser pickle , mais contrairement au JSON, les fichiers qu’il génère ne sont pas lisibles par l’homme, vous perdez donc la vérification visuelle que vous aimiez de votre ancienne méthode.

37
Amber

Pourquoi jouer avec toutes ces méthodes de sérialisation? Il est déjà écrit dans un fichier sous la forme d'un dict Python (bien qu'avec le nom malheureux 'dict'). Changez votre programme pour écrire les données avec un meilleur nom de variable - peut-être 'data' ou 'catalog', et enregistrez le fichier en tant que fichier Python, par exemple data.py. Ensuite, vous pouvez simplement importer les données directement au moment de l’exécution sans copier/coller maladroit ou JSON/shelve/etc. analyse:

from data import catalog
17
PaulMcG

Si les clés sont toutes des chaînes, vous pouvez utiliser le module shelve

Un shelf est un objet persistant, semblable à un dictionnaire. La différence avec les bases de données “Dbm” est que les valeurs (pas les clés!) Dans une étagère peuvent être Essentiellement des objets Python arbitraires - tout ce que le module pickle Peut gérer. Cela inclut la plupart des instances de classe, les types de données récursifs, Et les objets contenant de nombreux sous-objets partagés. Les clés sont Des chaînes ordinaires.

json serait un bon choix si vous devez utiliser les données d'autres langues

4
John La Rooy

JSON est probablement la bonne voie à suivre dans de nombreux cas; mais il pourrait y avoir une alternative. On dirait que vos clés et vos valeurs sont toujours des chaînes, est-ce vrai? Vous pouvez envisager d'utiliser dbm / anydbm . Ce sont des "bases de données" mais elles agissent presque exactement comme des dictionnaires. Ils sont parfaits pour la persistance des données à bas prix.

>>> 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'
4
senderle

Si l'efficacité du stockage est importante, utilisez Pickle ou CPickle (pour un gain de performance d'exécution). Comme Amber l'a souligné, vous pouvez également transférer/charger via Json. Il sera lisible par l'homme, mais nécessite plus de disque.

3
luanjunyi

Je vous suggère d’envisager d’utiliser le module shelve puisque votre structure de données est un mappage. C’était ma réponse à une question similaire intitulée Si je veux construire une base de données personnalisée, comment puis-je? Il y a aussi un peu de code exemple dans un autre réponse du mien qui en promeut l'utilisation pour la question Comment obtenir une base de données d'objets?

ActiveState a une recette PersistentDict très appréciée, qui prend en charge les formats de fichier de sortie csv, json et pickle. C'est assez rapide puisque ces trois formats sont implémentés en C (bien que la recette elle-même soit du pur Python), le fait qu'il lit le fichier entier en mémoire à l'ouverture peut être acceptable.

2
martineau

La sérialisation JSON (ou YAML, ou autre) est probablement préférable, mais si vous écrivez déjà le dictionnaire dans un fichier texte en syntaxe python, avec une liaison de nom de variable, vous pouvez simplement l'écrire dans un fichier .py. Ce fichier python serait alors importable et utilisable tel quel. Il n'est pas nécessaire d'utiliser l'approche "fonction qui retourne un dictionnaire", car vous pouvez directement l'utiliser en tant que global dans ce fichier. par exemple.

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

plutôt que:

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

La seule différence est que manually_copied.get_dict vous donne à chaque fois une nouvelle copie du dictionnaire, alors que generated.please_dont_use_dict_as_a_variable_name [1] est un objet partagé unique. Cela peut être important si vous modifiez le dictionnaire dans votre programme après l'avoir récupéré, mais vous pouvez toujours utiliser copy.copy ou copy.deepcopy pour créer une nouvelle copie si vous devez en modifier une indépendamment des autres.


[1] dict, list, str, int, map, etc. sont généralement considérés comme des noms de variables incorrects. La raison en est que ceux-ci sont déjà définis en tant que composants intégrés et sont utilisés très couramment. Donc, si vous nommez un nom comme celui-ci, au moins, cela entraînera une dissonance cognitive chez les personnes qui lisent votre code (y compris vous même après un certain temps d'absence), car elles doivent garder à l'esprit que "dict ne signifie pas". t signifie ce qu’il fait normalement ici ". Il est également fort probable qu’à un moment donné, vous obtiendrez un rapport de bogue exaspérant selon lequel les objets dict ne sont pas appelables (ou quelque chose d’autre), car un morceau de code tente d’utiliser la type dict , mais obtient l’objet dictionnaire lié au nom dict à la place.

0
Ben

sur la direction JSON, il y a aussi quelque chose appelé simpleJSON. La première fois que json utilisait json en python, la bibliothèque json ne fonctionnait pas pour moi/je ne pouvais pas le comprendre. simpleJSON était ... plus facile à utiliser

0
Tom