Wie serialisiere ich ein Python-Wörterbuch in eine Zeichenfolge und dann zurück in ein Wörterbuch? Das Wörterbuch enthält Listen und andere Wörterbücher.
Wie serialisiere ich ein Python-Wörterbuch in eine Zeichenfolge und dann zurück in ein Wörterbuch? Das Wörterbuch enthält Listen und andere Wörterbücher.
Antworten:
Es hängt davon ab, wofür Sie es verwenden möchten. Wenn Sie nur versuchen, es zu speichern, sollten Sie es verwenden pickle
(oder, wenn Sie CPython 2.x verwenden cPickle
, das schneller ist).
>>> import pickle
>>> pickle.dumps({'foo': 'bar'})
b'\x80\x03}q\x00X\x03\x00\x00\x00fooq\x01X\x03\x00\x00\x00barq\x02s.'
>>> pickle.loads(_)
{'foo': 'bar'}
Wenn Sie möchten, dass es lesbar ist, können Sie Folgendes verwenden json
:
>>> import json
>>> json.dumps({'foo': 'bar'})
'{"foo": "bar"}'
>>> json.loads(_)
{'foo': 'bar'}
json
ist jedoch sehr begrenzt in der Unterstützung, während pickle
es für beliebige Objekte verwendet werden kann (wenn es nicht automatisch funktioniert, kann die Klasse definieren __getstate__
, um genau anzugeben, wie es eingelegt werden soll).
>>> pickle.dumps(object())
b'\x80\x03cbuiltins\nobject\nq\x00)\x81q\x01.'
>>> json.dumps(object())
Traceback (most recent call last):
...
TypeError: <object object at 0x7fa0348230c0> is not JSON serializable
In Python 3.0... Users should always import the standard version, which attempts to import the accelerated version and falls back to the pure Python version.
Verwenden Sie das json- Modul von Python oder simplejson, wenn Sie nicht über Python 2.6 oder höher verfügen.
json.dumps(mydict)
undjson.loads(mystring)
json.dumps()
kümmern sich um einige Arten ( False
, True
, und None
) , weil sie mit nicht kompatibel sindjson
Wenn Sie der Zeichenfolge voll vertrauen und sich nicht für Python-Injektionsangriffe interessieren, ist dies eine sehr einfache Lösung:
d = { 'method' : "eval", 'safe' : False, 'guarantees' : None }
s = str(d)
d2 = eval(s)
for k in d2:
print k+"="+d2[k]
Wenn Sie sicherheitsbewusster sind, ast.literal_eval
ist dies eine bessere Wahl.
ast.literal_eval
standardmäßig verwenden. eval
hat keine Mehrwert und ein großes Sicherheitsproblem.
eval
weg können. Ich bin jedes Mal nur angewidert, jemand fördert diese Kultur der Schlamperei. Verwenden Sie einfach json.dumps
und json.loads
(oder eine andere Nichtlösung eval
), es gibt keinen wirklichen Grund, dies nicht zu
Pickle ist großartig, aber ich denke, es ist erwähnenswert, literal_eval
das ast
Modul für eine noch leichtere Lösung zu erwähnen, wenn Sie nur grundlegende Python-Typen serialisieren. Es ist im Grunde eine "sichere" Version der berüchtigten eval
Funktion, die nur die Bewertung grundlegender Python-Typen im Gegensatz zu einem gültigen Python-Code ermöglicht.
Beispiel:
>>> d = {}
>>> d[0] = range(10)
>>> d['1'] = {}
>>> d['1'][0] = range(10)
>>> d['1'][1] = 'hello'
>>> data_string = str(d)
>>> print data_string
{0: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], '1': {0: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 1: 'hello'}}
>>> from ast import literal_eval
>>> d == literal_eval(data_string)
True
Ein Vorteil ist, dass die serialisierten Daten nur Python-Code sind und daher sehr menschenfreundlich sind. Vergleichen Sie es mit dem, was Sie bekommen würden pickle.dumps
:
>>> import pickle
>>> print pickle.dumps(d)
(dp0
I0
(lp1
I0
aI1
aI2
aI3
aI4
aI5
aI6
aI7
aI8
aI9
asS'1'
p2
(dp3
I0
(lp4
I0
aI1
aI2
aI3
aI4
aI5
aI6
aI7
aI8
aI9
asI1
S'hello'
p5
ss.
Der Nachteil ist, dass Sie, sobald die Daten einen Typ enthalten, der von nicht unterstützt wird literal_ast
, zu etwas anderem wie Beizen übergehen müssen.
Eine Sache, json
die nicht getan werden kann, ist die dict
Indizierung mit Ziffern. Das folgende Snippet
import json
dictionary = dict({0:0, 1:5, 2:10})
serialized = json.dumps(dictionary)
unpacked = json.loads(serialized)
print(unpacked[0])
wird werfen
KeyError: 0
Weil Schlüssel in Zeichenfolgen konvertiert werden. cPickle
behält den numerischen Typ bei und das entpackte dict
kann sofort verwendet werden.
Obwohl dies keine strikte Serialisierung ist, kann json hier ein vernünftiger Ansatz sein. Damit werden verschachtelte Dikte und Listen sowie Daten behandelt, solange Ihre Daten "einfach" sind: Zeichenfolgen und grundlegende numerische Typen.
Pyyaml sollte auch hier erwähnt werden. Es ist sowohl für Menschen lesbar als auch kann jedes Python-Objekt serialisieren.
pyyaml wird hier gehostet:
https://bitbucket.org/xi/pyyaml
Wenn Sie nur serialisieren möchten, ist pprint möglicherweise auch eine gute Option. Es erfordert die Serialisierung des Objekts und einen Dateistream.
Hier ist ein Code:
from pprint import pprint
my_dict = {1:'a',2:'b'}
with open('test_results.txt','wb') as f:
pprint(my_dict,f)
Ich bin mir nicht sicher, ob wir leicht deserialisieren können. Ich habe json früher zum Serialisieren und Deserialisieren verwendet, was in den meisten Fällen korrekt funktioniert.
f.write(json.dumps(my_dict, sort_keys = True, indent = 2, ensure_ascii=True))
In einem bestimmten Fall gab es jedoch einige Fehler beim Schreiben von Nicht-Unicode-Daten in json.
pickle
?