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.

556
demandé sur Bhargav Rao 2009-06-12 22:25:02

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
881
répondu Jacob Gabrielson 2017-04-27 16:54:32

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

135
répondu ir0x539 2017-05-23 12:02:58

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'>
88
répondu tokhi 2018-06-12 20:25:00

à 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'}
24
répondu lqhcpsgbl 2016-06-28 03:20:03

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.

20
répondu Blixt 2009-06-12 18:30:12

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!

19
répondu Rogerio Silveira 2018-06-12 20:25:39

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'
7
répondu Walk 2017-02-10 12:02:47

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.

5
répondu Ned Batchelder 2009-06-12 19:09:31
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
4
répondu Siva Kameswara Rao Munipalle 2018-10-13 14:00:43

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

3
répondu Anatoly Alekseev 2018-07-19 23:20:05

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é".

1
répondu Tamerlaha 2018-06-12 20:26:08