我如何序列化一个Python字典到一个string,然后回到一个字典?
我如何序列化一个Python字典到一个string,然后回到一个字典? 字典里面会有列表和其他字典。
这取决于你想要使用它。 如果你只是想保存它,你应该使用pickle
(或者cPickle
,如果你使用的是CPython,速度会更快)。
>>> import cPickle >>> cPickle.dumps({'foo': 'bar'}) "(dp1\nS'foo'\np2\nS'bar'\np3\ns." >>> cPickle.loads(_) {'foo': 'bar'}
但是,如果你想让它可读,你可以使用json
>>> import json >>> json.dumps({'foo': 'bar'}) '{"foo": "bar"}' >>> json.loads(_) {u'foo': u'bar'}
或simplejson
。
>>> import simplejson >>> simplejson.dumps({'foo': 'bar'}) '{"foo": "bar"}' >>> simplejson.loads(_) {'foo': 'bar'}
json
和simplejson
在他们的支持上是非常有限的。 cPickle
可以用于对象(如果它不能自动工作,类可以定义__getstate__
来精确地指定它应该如何被pickle)。
>>> cPickle.dumps(object()) 'ccopy_reg\n_reconstructor\np1\n(c__builtin__\nobject\np2\ng2\nNtRp3\n.' >>> json.dumps(object()) Traceback (most recent call last): ... TypeError: <object object at 0x7fa0348230c0> is not JSON serializable >>> simplejson.dumps(object()) Traceback (most recent call last): ... TypeError: <object object at 0x7fa034823090> is not JSON serializable
如果你没有Python 2.6或更高版本,请使用Python的json模块,或simplejson 。
如果你完全信任这个string,并且不关心python注入攻击,那么这是非常简单的解决scheme:
d = { 'method' : "eval", 'safe' : False, 'guarantees' : None } s = str(d) d2 = eval(s) for k in d2: print k+"="+d2[k]
如果你更有安全意识,那么ast.literal_eval
是一个更好的select。
泡菜是伟大的,但我认为值得一提的ast
模块literal_eval
更轻量级的解决scheme,如果你只是序列化基本的Pythontypes。 它基本上是臭名昭着的eval
函数的“安全”版本,只允许评估基本的pythontypes,而不是任何有效的python代码。
例:
>>> 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
一个好处是序列化的数据只是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
支持的types,就必须转换到酸洗之类的东西。
json
不能做的一件事就是用数字索引dict
。 以下片段
import json dictionary = dict({0:0, 1:5, 2:10}) serialized = json.dumps(dictionary) unpacked = json.loads(serialized) print unpacked[0]
会抛出
KeyError: 0
因为密钥被转换为string。 cPickle
保留数字types,解压后的dict
可以立即使用。
虽然没有严格的序列化,但json在这里可能是合理的方法。 这将处理嵌套的字典和列表,以及数据,只要你的数据是“简单的”:string和基本的数字types。
pyyaml也应该在这里提到。 它是人类可读的,可以序列化任何python对象。
pyyaml在这里托pipe:
https://bitbucket.org/xi/pyyaml
如果你只是尝试序列化,那么pprint也可能是一个不错的select。 它需要对象被序列化和文件stream。
这是一些代码:
from pprint import pprint my_dict = {1:'a',2:'b'} with open('test_results.txt','wb') as f: pprint(my_dict,f)
我不确定是否可以轻松地反序列化。 我正在使用JSON序列化和反序列化在大多数情况下正常工作。
f.write(json.dumps(my_dict, sort_keys = True, indent = 2, ensure_ascii=True))
但是,在一个特定的情况下,将非Unicode数据写入json时出现了一些错误。