Convertir une chaîne de représentation D'un dictionnaire en un dictionnaire?
comment transformer la représentation str
d'une dict
, telle que la chaîne suivante, en une dict
?
s = "{'muffin' : 'lolz', 'foo' : 'kitty'}"
je préfère ne pas utiliser eval
. Quoi d'autre puis-je utiliser?
la raison principale de cela, est l'un de mes collègues classes il a écrit, convertit toutes les entrées en cordes. Je ne suis pas d'humeur à modifier ses cours, pour régler ce problème.
11 réponses
à partir de Python 2.6, vous pouvez utiliser le ast.literal_eval
:
>>> import ast
>>> ast.literal_eval("{'muffin' : 'lolz', 'foo' : 'kitty'}")
{'muffin': 'lolz', 'foo': 'kitty'}
C'est plus sûr que d'utiliser eval
. Comme ses propres docs disent:
>>> help(ast.literal_eval) Help on function literal_eval in module ast: literal_eval(node_or_string) Safely evaluate an expression node or a string containing a Python expression. The string or node provided may only consist of the following Python literal structures: strings, numbers, tuples, lists, dicts, booleans, and None.
par exemple:
>>> eval("shutil.rmtree('mongo')")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
File "/opt/Python-2.6.1/lib/python2.6/shutil.py", line 208, in rmtree
onerror(os.listdir, path, sys.exc_info())
File "/opt/Python-2.6.1/lib/python2.6/shutil.py", line 206, in rmtree
names = os.listdir(path)
OSError: [Errno 2] No such file or directory: 'mongo'
>>> ast.literal_eval("shutil.rmtree('mongo')")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/opt/Python-2.6.1/lib/python2.6/ast.py", line 68, in literal_eval
return _convert(node_or_string)
File "/opt/Python-2.6.1/lib/python2.6/ast.py", line 67, in _convert
raise ValueError('malformed string')
ValueError: malformed string
http://docs.python.org/2/library/json.html
JSON peut résoudre ce problème bien que son Décodeur veuille des guillemets doubles autour des clés et des valeurs. Si ça ne vous dérange pas un piratage de remplacement...
import json
s = "{'muffin' : 'lolz', 'foo' : 'kitty'}"
json_acceptable_string = s.replace("'", "\"")
d = json.loads(json_acceptable_string)
# d = {u'muffin': u'lolz', u'foo': u'kitty'}
notez que si vous avez des guillemets simples comme partie de vos clés ou de vos valeurs, cela échouera en raison d'un remplacement de caractère incorrect. Cette solution n'est recommandée que si vous avez une forte aversion pour la solution eval.
en savoir Plus sur json simple citation: jQuery de devis unique en réponse JSON
par json.loads
:
>>> import json
>>> h = '{"foo":"bar", "foo2":"bar2"}'
>>> type(h)
<type 'str'>
>>> d = json.loads(h)
>>> d
{u'foo': u'bar', u'foo2': u'bar2'}
>>> type(d)
<type 'dict'>
à L'exemple de OP:
s = "{'muffin' : 'lolz', 'foo' : 'kitty'}"
nous pouvons utiliser Yaml pour traiter ce genre de JSON non standard dans la chaîne:
>>> import yaml
>>> s = "{'muffin' : 'lolz', 'foo' : 'kitty'}"
>>> s
"{'muffin' : 'lolz', 'foo' : 'kitty'}"
>>> yaml.load(s)
{'muffin': 'lolz', 'foo': 'kitty'}
si la chaîne peut toujours être fiable, vous pouvez utiliser eval
(ou utiliser literal_eval
comme suggéré; c'est sans danger peu importe ce que la chaîne est.) Sinon vous avez besoin d'un analyseur. Un analyseur JSON (comme simplejson) fonctionnerait s'il ne stockait que du contenu compatible avec le schéma JSON.
utiliser json
. la bibliothèque ast
consomme beaucoup de mémoire et et plus lent. J'ai un processus qui a besoin de lire un fichier texte de 156mo. Ast
avec 5 minutes de retard pour le dictionnaire de conversion json
et 1 minute en utilisant 60% moins de mémoire!
vous pouvez essayer ceci.
>>> import ast
>>> data = "{'user': 'bob', 'age': 10, 'grades': ['A', 'F', 'C']}"
>>> ast.literal_eval(data)
O/P: {'age': 10, 'grades': ['A', 'F', 'C'], 'user': 'bob'}
>>> user = ast.literal_eval(data)
>>> user['age']
O/P: 10
>>> user['grades']
O/P: ['A', 'F', 'C']
>>> user['user']
O/P: 'bob'
si vous ne pouvez pas utiliser Python 2.6, vous pouvez utiliser une simple implementation safeeval comme http://code.activestate.com/recipes/364469/
ça coagule sur le compilateur Python pour que vous n'ayez pas à faire tout le travail vous-même.
string = "{'server1':'value','server2':'value'}"
#Now removing { and }
s = string.replace("{" ,"")
finalstring = s.replace("}" , "")
#Splitting the string based on , we get key value pairs
list = finalstring.split(",")
dictionary ={}
for i in list:
#Get Key Value pairs separately to store in dictionary
keyvalue = i.split(":")
#Replacing the single quotes in the leading.
m= keyvalue[0].strip('\'')
m = m.replace("\"", "")
dictionary[m] = keyvalue[1].strip('"\'')
print dictionary
pour résumer:
import ast, yaml, json, timeit
descs=['short string','long string']
strings=['{"809001":2,"848545":2,"565828":1}','{"2979":1,"30581":1,"7296":1,"127256":1,"18803":2,"41619":1,"41312":1,"16837":1,"7253":1,"70075":1,"3453":1,"4126":1,"23599":1,"11465":3,"19172":1,"4019":1,"4775":1,"64225":1,"3235":2,"15593":1,"7528":1,"176840":1,"40022":1,"152854":1,"9878":1,"16156":1,"6512":1,"4138":1,"11090":1,"12259":1,"4934":1,"65581":1,"9747":2,"18290":1,"107981":1,"459762":1,"23177":1,"23246":1,"3591":1,"3671":1,"5767":1,"3930":1,"89507":2,"19293":1,"92797":1,"32444":2,"70089":1,"46549":1,"30988":1,"4613":1,"14042":1,"26298":1,"222972":1,"2982":1,"3932":1,"11134":1,"3084":1,"6516":1,"486617":1,"14475":2,"2127":1,"51359":1,"2662":1,"4121":1,"53848":2,"552967":1,"204081":1,"5675":2,"32433":1,"92448":1}']
funcs=[json.loads,eval,ast.literal_eval,yaml.load]
for desc,string in zip(descs,strings):
print('***',desc,'***')
print('')
for func in funcs:
print(func.__module__+' '+func.__name__+':')
%timeit func(string)
print('')
Résultats:
*** short string ***
json loads:
4.47 µs ± 33.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
builtins eval:
24.1 µs ± 163 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
ast literal_eval:
30.4 µs ± 299 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
yaml load:
504 µs ± 1.29 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
*** long string ***
json loads:
29.6 µs ± 230 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
builtins eval:
219 µs ± 3.92 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
ast literal_eval:
331 µs ± 1.89 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
yaml load:
9.02 ms ± 92.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Conclusion: préférez json.charges
pas de toutes les libs sont utilisés:
dict_format_string = "{'1':'one', '2' : 'two'}"
d = {}
elems = filter(str.isalnum,dict_format_string.split("'"))
values = elems[1::2]
keys = elems[0::2]
d.update(zip(keys,values))
NOTE: Comme il a le code dur split("'")
ne fonctionnera que pour les chaînes où les données sont"simple Cité".