Convertir un dict python en chaîne et inversement

275

J'écris un programme qui stocke des données dans un objet dictionnaire, mais ces données doivent être enregistrées à un moment donné pendant l'exécution du programme et rechargées dans l'objet dictionnaire lorsque le programme est exécuté à nouveau. Comment convertir un objet dictionnaire en une chaîne qui peut être écrite dans un fichier et rechargée dans un objet dictionnaire? Nous espérons que cela supportera les dictionnaires contenant des dictionnaires.

AJ00200
la source

Réponses:

274

Le module json est ici une bonne solution. Il a les avantages par rapport au cornichon qu'il ne produit qu'une sortie en texte brut, et est multiplateforme et multi-version.

import json
json.dumps(dict)
Tyler Eaves
la source
2
J'examinerai également ce module. Json et pickle semblent assez faciles à utiliser, donc cela se résumera à des choses telles que le support multiplateforme. Merci
AJ00200
5
Le cornichon a tendance à être considéré comme plutôt obsolète à ce stade. J'utilise toujours json pour des choses comme ça. Être (relativement) lisible par l'homme est un GRAND plus la plupart du temps.
Tyler Eaves
30
Vous devez ajouter un exemple simple pour permettre aux utilisateurs de voir comment procéder.
Miguel Vazq
1
@TylerEaves Pouvez-vous fournir un exemple de la façon dont cela devrait être fait.
Boban
1
: frontslap: n'oubliez pas ce import jsonque j'ai fait!
Jesse Chisholm
207

Si votre dictionnaire n'est pas trop gros, str + eval peut faire le travail:

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

dict2 = eval(str1)

print dict1==dict2

Vous pouvez utiliser ast.literal_eval au lieu de eval pour plus de sécurité si la source n'est pas fiable.

PabloG
la source
13
Je ne suis pas vraiment prêt à faire face aux possibles exploits que cela pourrait introduire dans le code. Je ne sais pas quels problèmes json ou cornichon pourrait avoir, mais je sais pertinemment que l'eval serait dangereux dans ce cas.
AJ00200
5
@ AJ00200: et l'alternative ast.literal_eval que j'ai mentionnée?. À partir de l'aide de Python: "Évaluez en toute sécurité un nœud d'expression ou une chaîne contenant une expression Python. La chaîne ou le nœud fourni ne peut comprendre que les structures littérales Python suivantes: chaînes, nombres, tuples, listes, dictés, booléens et aucun. peut être utilisé pour évaluer en toute sécurité des chaînes contenant des expressions Python à partir de sources non fiables sans avoir à analyser les valeurs soi-même. "
PabloG
Cela semble utile, mais lorsque j'utilisais précédemment SQLite pour gérer ces données et qu'il y avait plus de 1500 entrées, il est donc assez grand et en croissance constante.
AJ00200
164

J'utilise json:

import json

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

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

Utilisez le picklemodule pour l'enregistrer sur le disque et le charger plus tard.

ismail
la source
2
@extraneon En fait, c'est une réponse à la question. Il le convertit quelque part en chaîne et l'écrit dans un fichier. Je n'ai pas besoin de faire la conversion ou l'écriture de fichiers car ils sont tous encapsulés par des cornichons.
AJ00200
12

Pourquoi ne pas utiliser la fonction literal_eval de la bibliothèque ast intégrée de Python 3 . Il vaut mieux utiliser literal_eval au lieu de eval

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

donnera la sortie en tant que véritable dictionnaire

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

Et si vous demandez à convertir un dictionnaire en chaîne , que diriez-vous d'utiliser str () méthode de Python.

Supposons que le dictionnaire soit:

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

Et cela se fera comme ceci:

str(my_dict)

Imprime:

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

C'est aussi simple que vous le souhaitez.

FightWithCode
la source
5

Si dans 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')
bêta
la source
1
Ce serait une meilleure réponse si vous expliquiez comment le code que vous avez fourni répond à la question.
pppery
4

Convertir le dictionnaire en JSON (chaîne)

import json 

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

result = json.dumps(mydict)

print(result[0:20])

vous obtiendrez:

{"nom": "Don", "sur

Convertir une chaîne en dictionnaire

back_to_mydict = json.loads(result) 
Harvey
la source
3

Je pense que vous devriez envisager d'utiliser le shelvemodule qui fournit des objets persistants de type dictionnaire sauvegardés sur fichier. Il est facile à utiliser à la place d'un "vrai" dictionnaire car il fournit de manière presque transparente à votre programme quelque chose qui peut être utilisé comme un dictionnaire, sans avoir besoin de le convertir explicitement en chaîne, puis d'écrire dans un fichier (ou vice- vice versa).

La principale différence est de devoir d'abord le open()faire avant la première utilisation, puis de le close()faire lorsque vous avez terminé (et éventuellement de sync()le faire, selon lewriteback option utilisée). Tout objet fichier "étagère" créé peut contenir des dictionnaires normaux en tant que valeurs, ce qui leur permet d'être imbriqués logiquement.

Voici un exemple 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()

Production:

{'three': {'three.1': 3.1, 'three.2': 3.2}, 'two': 2, 'one': 1}
martineau
la source
2

Si vous vous souciez de la vitesse, utilisez ujson (UltraJSON), qui a la même 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
la source
1

J'utilise yaml si cela doit être lisible (ni JSON ni XML ne sont à mon humble avis), ou si la lecture n'est pas nécessaire, j'utilise cornichon.

Écrire

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)

Relire

from pickle import dumps, loads
rev = loads(open('/var/tmp/dump.txt').read())
print rev
Gérard
la source
Vous devez vraiment utiliser le bdrapeau lors de l'ouverture du fichier ici.
Piotr Dobrogost
1
J'aurais pu être plus explicite. Cependant, par dumps()défaut, le protocole 0, qui est un protocole ascii. C'est pourquoi 'rb'n'est pas nécessaire à mon humble avis.
Gerard