1183 Stimmen

Eine String-Darstellung eines Wörterbuchs in ein Wörterbuch umwandeln?

Wie kann ich die str Darstellung einer dict wie etwa die folgende Zeichenkette, in eine dict ?

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

Ich ziehe es vor, nicht zu verwenden eval . Was kann ich noch verwenden?

Der Hauptgrund dafür ist, dass eine Klasse, die ein Kollege von mir geschrieben hat, alle Eingaben in Strings umwandelt. Ich bin nicht in der Stimmung zu gehen und seine Klassen zu ändern, um mit diesem Problem umzugehen.

2 Stimmen

Wenn Sie Python 2.6 nicht verwenden können, können Sie eine einfache safeeval-Implentation verwenden wie code.activestate.com/rezepte/364469 Es setzt auf den Python-Compiler auf, so dass Sie nicht selbst die ganze Arbeit machen müssen.

30 Stimmen

Hinweis : Für diejenigen, die hierher kommen mit täuschend ähnlich aussehend JSON Daten, wollen Sie lesen gehen JSON in Python parsen stattdessen. JSON ist nicht dasselbe wie Python . Wenn Sie " doppelte Anführungszeichen um Ihre Zeichenketten haben Sie wahrscheinlich JSON-Daten. Sie können auch nach null , true o false Die Python-Syntax verwendet None , True y False .

1715voto

Jacob Gabrielson Punkte 32161

Sie können die integrierte ast.literal_eval :

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

Dies ist sicherer als die Verwendung von eval . Wie es in den eigenen Unterlagen heißt:

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

Zum Beispiel:

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

1 Stimmen

Ich sollte hinzufügen, dass Sie die Zeichenfolge für die Verwendung mit ast.literal_eval bereinigen müssen. (sicherstellen, dass Anführungszeichen/Doppelanführungszeichen in der Zeichenkette escaped werden)

0 Stimmen

Ich erhalte diese Fehlermeldung Ich benutze Python 2.6 (x86) auf Windows 7 x64 File " D:\Python26\lib\ast.py ", Zeile 48, in literal_eval node_or_string = parse(node_or_string, mode='eval') Datei " D:\Python26\lib\ast.py ", Zeile 36, in parse return compile(expr, filename, mode, PyCF_ONLY_AST) Datei "<unknown>", Zeile 1 ^ SyntaxError: ungültige Syntax

2 Stimmen

Was ist mit "dict(a=1)" Stil-Saiten?

419voto

0x539 Punkte 3927

https://docs.python.org/3.8/library/json.html

JSON kann dieses Problem lösen, obwohl sein Decoder doppelte Anführungszeichen um Schlüssel und Werte herum verlangt. Wenn Sie nichts gegen einen replace hack haben...

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

HINWEIS: Wenn Sie einfache Anführungszeichen als Teil Ihrer Schlüssel oder Werte verwenden, wird dies aufgrund einer falschen Zeichenersetzung fehlschlagen. Diese Lösung wird nur empfohlen, wenn Sie eine starke Abneigung gegen die eval-Lösung haben.

Mehr über json single quote: jQuery.parseJSON wirft "Ungültiges JSON"-Fehler aufgrund von escapeten einfachen Anführungszeichen in JSON

4 Stimmen

Ich habe nach dieser Lösung gesucht. +1 um mitzuteilen, dass der Decoder doppelte Anführungszeichen um Schlüssel und Werte wünscht.

5 Stimmen

Ein weiteres Problem ist für "{0: 'Hello'}" .

5 Stimmen

Dies schlägt auch fehl, wenn Sie Kommas am Ende haben (nicht JSON-konform), z. B.: "{'muffin' : 'lolz', 'foo' : 'kitty',}"

241voto

tokhi Punkte 19702

Mit json.loads :

>>> import json
>>> h = '{"foo":"bar", "foo2":"bar2"}'
>>> d = json.loads(h)
>>> d
{u'foo': u'bar', u'foo2': u'bar2'}
>>> type(d)
<type 'dict'>

27 Stimmen

Ich glaube nicht, dass dies eine Antwort auf die Frage des Auftraggebers ist. Wie können wir json.laads verwenden, um einen String s = "{'muffin' : 'lolz', 'foo' : 'kitty'}" in dict zu konvertieren?

0 Stimmen

Warum wird 'u' in der Ausgabe gedruckt? z.B. - str = '{"1": "P", "2": "N", "3": "M"}' d = json.loads(str) print d Ausgabe ist : {u'1': u'P', u'3': u'M', u'2': u'N'}

4 Stimmen

@technazi: json.loads(h.replace("'",'"'))

55voto

lqhcpsgbl Punkte 3524

Zum Beispiel von OP:

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

Wir können verwenden Yaml um mit dieser Art von Nicht-Standard-Json in String umzugehen:

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

9 Stimmen

Dadurch werden die Zeichenketten "Ja" und "Nein" in Wahr/Falsch umgewandelt.

0 Stimmen

Ich habe meinen Wert, der funktioniert gut....aber ich bekomme einen Fehler mit ihm "AMLLoadWarning: Aufruf yaml.load() ohne Loader=... ist veraltet, da die Standard-Loader unsicher ist. Bitte lesen msg.pyyaml.org/load für alle Einzelheiten".

1 Stimmen

Verwenden Sie diesen yaml-Parser nur für vertrauenswürdig Eingabe. Verwenden Sie vorzugsweise safe_load um Auswirkungen auf die Sicherheit zu vermeiden.

36voto

Anatoly Alekseev Punkte 1514

Zusammengefasst:

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

Ergebnisse:

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

Schlussfolgerung: vorziehen. json.lädt

14 Stimmen

Allerdings funktioniert das nicht mit der Zeichenkette in einfachen Anführungszeichen, was Teil des ursprünglichen Problems war. Die Leistung wurde nie erwähnt.

5 Stimmen

+1 für die Benchmarks (sie helfen, eine fundierte Entscheidung zu treffen), -1 für die Schlussfolgerung: wie bereits mehrfach erwähnt, json scheitert in vielen Fällen. Es sollte dem Benutzer überlassen bleiben, zwischen Funktionen und Leistung zu wählen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X