Question Convertir une représentation de chaîne d'un dictionnaire dans un dictionnaire?


Comment puis-je convertir le str représentation d'un dict, comme la chaîne suivante, dans un dict?

s = "{'muffin' : 'lolz', 'foo' : 'kitty'}"

Je préfère ne pas utiliser eval. Que puis-je utiliser d'autre?

La raison principale pour cela, est l'une de mes classes de collègues qu'il a écrit, convertit toutes les entrées en chaînes. Je ne suis pas d'humeur à aller modifier ses cours pour faire face à ce problème.


531
2018-06-12 18:25


origine


Réponses:


À partir de Python 2.6, vous pouvez utiliser le built-in 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 le disent ses propres docteurs:

>>> aide (ast.literal_eval)
Aide sur la fonction literal_eval dans le module ast:

literal_eval (node_or_string)
    Évaluer en toute sécurité un noeud d'expression ou une chaîne contenant un Python
    expression. La chaîne ou le noeud fourni ne peut être composé que des éléments suivants
    Structures littérales Python: chaînes, nombres, tuples, listes, dicts, booléens,
    et aucun.

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

850
2018-06-12 18:30



http://docs.python.org/2/library/json.html

JSON peut résoudre ce problème même si son décodeur veut des guillemets doubles autour des clés et des valeurs. Si cela ne vous dérange pas un hack 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 dans le cadre de vos clés ou de vos valeurs, cela échouera en raison du remplacement incorrect des caractères. Cette solution n'est recommandée que si vous avez une forte aversion pour la solution eval.

Plus au sujet de la citation simple de json: Guillemet simple jQuery dans la réponse JSON


123
2017-10-15 21:54



en utilisant 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'>

80
2017-08-15 12:07



Pour l'exemple de l'OP:

s = "{'muffin' : 'lolz', 'foo' : 'kitty'}"

On peut utiliser Yaml pour faire face à ce genre de json non standard en chaîne:

>>> import yaml
>>> s = "{'muffin' : 'lolz', 'foo' : 'kitty'}"
>>> s
"{'muffin' : 'lolz', 'foo' : 'kitty'}"
>>> yaml.load(s)
{'muffin': 'lolz', 'foo': 'kitty'}

21
2018-06-28 03:20



Si la chaîne peut toujours faites confiance, vous pourriez utiliser eval (Ou utiliser literal_eval comme suggéré; c'est sûr quelle que soit la chaîne.) Sinon, vous avez besoin d'un analyseur. Un analyseur JSON (tel que simplejson) fonctionnerait s'il ne stockait que du contenu compatible avec le schéma JSON.


20
2018-06-12 18:30



Utilisation json. la ast bibliothèque consomme beaucoup de mémoire et plus lent. J'ai un processus qui a besoin de lire un fichier texte de 156 Mo. Ast avec 5 minutes de retard pour le dictionnaire de conversion json et 1 minutes en utilisant 60% moins de mémoire!


19
2017-08-27 12:50



Si vous ne pouvez pas utiliser Python 2.6, vous pouvez utiliser une implémentation safeeval simple comme http://code.activestate.com/recipes/364469/

Il se superpose au compilateur Python pour que vous n'ayez pas à faire tout le travail brut vous-même.


5
2018-06-12 19:09



Tu peux essayer ça.

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

5
2018-02-09 11:05