Pregunta Convierta una representación de cadena de un diccionario a un diccionario?


¿Cómo puedo convertir el str representación de un dict, como la siguiente cadena, en una dict?

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

Prefiero no usar eval. ¿Qué más puedo usar?

La razón principal de esto, es una de mis clases de compañeros de trabajo que escribió, convierte todas las entradas en cadenas. No estoy de humor para ir y modificar sus clases para lidiar con este problema.


532
2018-06-12 18:25


origen


Respuestas:


Comenzando en Python 2.6 puede usar el built-in ast.literal_eval:

>>> import ast
>>> ast.literal_eval("{'muffin' : 'lolz', 'foo' : 'kitty'}")
{'muffin': 'lolz', 'foo': 'kitty'}

Esto es más seguro que usar eval. Como sus propios documentos dicen:

>>> ayuda (ast.literal_eval)
Ayuda sobre la función literal_eval en el módulo ast:

literal_eval (node_or_string)
    Evaluar de forma segura un nodo de expresión o una cadena que contiene un Python
    expresión. La cadena o nodo proporcionado solo puede consistir en lo siguiente
    Estructuras literales de Python: cadenas, números, tuplas, listas, dictos, booleanos,
    y ninguno

Por ejemplo:

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

851
2018-06-12 18:30



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

JSON puede resolver este problema aunque su decodificador quiere comillas dobles para claves y valores. Si no te importa reemplazar un truco ...

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

TENGA EN CUENTA que si tiene comillas simples como parte de sus claves o valores, esto fallará debido a la sustitución incorrecta de caracteres. Esta solución solo se recomienda si tiene una fuerte aversión a la solución eval.

Más acerca de json single quote: jQuery comilla simple en respuesta JSON


123
2017-10-15 21:54



utilizando 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



Para el ejemplo de OP:

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

Nosotros podemos usar Yaml para tratar con este tipo de JSON no estándar en una cadena:

>>> 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 cuerda puede siempre ser confiable, podrías usar eval (o usar literal_eval como se sugirió; es seguro sin importar cuál sea la cadena.) De lo contrario, necesita un analizador. Un analizador JSON (como simplejson) funcionaría si solo almacena contenido que se ajuste al esquema JSON.


20
2018-06-12 18:30



Utilizar json. el ast la biblioteca consume mucha memoria yy más lento. Tengo un proceso que necesita leer un archivo de texto de 156Mb. Ast con 5 minutos de retraso para el diccionario de conversión json ¡y 1 minuto usando un 60% menos de memoria!


19
2017-08-27 12:50



Si no puede usar Python 2.6, puede usar una implementación simple de seguridad como http://code.activestate.com/recipes/364469/

Se conecta al compilador de Python para que no tenga que hacer todo el trabajo bruto usted mismo.


5
2018-06-12 19:09