web-dev-qa-db-ja.com

Python辞書を文字列にシリアル化してから辞書に戻すにはどうすればよいですか?

Python辞書を文字列にシリアル化してから辞書に戻すにはどうすればよいですか?辞書にはリストや他の辞書が含まれます。

59
TIMEX

それはあなたがそれを使用したいものに依存します。保存しようとしている場合は、 pickle を使用する必要があります(または、CPython 2.xを使用している場合は、 cPickle 、これは高速です)。

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

読みやすくしたい場合は、 json を使用できます。

>>> import json
>>> json.dumps({'foo': 'bar'})
'{"foo": "bar"}'
>>> json.loads(_)
{'foo': 'bar'}

ただし、jsonはサポート対象が非常に制限されていますが、pickleは任意のオブジェクトに使用できます(自動的に機能しない場合、クラスは__getstate__どのようにピクルスにするかを正確に指定します)。

>>> 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
96
Chris Morgan

Pythonの json モジュールを使用するか、=がない場合は simplejson を使用しますpython 2.6以降。

11
Dan D.

Pickleは素晴らしいですが、基本的なpython型のみをシリアル化する場合、さらに軽量なソリューションのためにastモジュールのliteral_evalに言及する価値があると思います。基本的には有効なpythonコードに対して、基本的なpythonタイプの評価のみを許可する悪名高いeval関数の「安全な」バージョン。

例:

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

利点の1つは、シリアル化されたデータがpythonコードであるため、非常に人間に優しいことです。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.

欠点は、データにliteral_astでサポートされていない型が含まれるとすぐに、ピクルスなどの別のものに移行する必要があることです。

10
Graphics Noob

If文字列を完全に信頼し、 pythonインジェクション攻撃 を気にしない場合、これは非常に簡単なソリューションです:

d = { 'method' : "eval", 'safe' : False, 'guarantees' : None }
s = str(d)
d2 = eval(s)
for k in d2:
    print k+"="+d2[k]

あなたがより安全を意識しているなら、 ast.literal_eval の方が良い方法です。

10
yoyo

jsonができないことの1つは、数字でインデックス付けされたdictです。次のスニペット

import json
dictionary = dict({0:0, 1:5, 2:10})
serialized = json.dumps(dictionary)
unpacked   = json.loads(serialized)
print unpacked[0]

投げます

KeyError: 0

キーが文字列に変換されるため。 cPickleは数値型を保持し、解凍されたdictはすぐに使用できます。

4
Przemek D

pyyamlもここに記載する必要があります。人間が読める形式であり、任意のpythonオブジェクトをシリアル化できます。
pyyamlはここでホストされます:
https://bitbucket.org/xi/pyyaml

1
georg

厳密にシリアライズされていませんが、ここではjsonが妥当なアプローチかもしれません。データが「単純」である限り、ネストされた辞書とリスト、およびデータを処理します:文字列と基本的な数値型。

1
Tyler Eaves