序列化与反序列化

把变量从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等。序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上。反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。Python提供了几个模块来实现序列化。

pickle模块

pickle.dump(obj, file, protocol=None, *, fix_imports=True)
obj:序列化的对象
file:写入的文件对象。必须具有接受单个字节参数的write()方法。
protocol:使用的协议。是个整数,支持0到HIGHEST_PROTOCOL。 如果未指定,则默认为DEFAULT_PROTOCOL。 如果指定了负数,则选择HIGHEST_PROTOCOL。 fix_imports:默认True。

将obj对象序列化后,写入到file-like Object文件。这相当于Pickler(file, protocol).dump(obj)。如果fix_imports为True且protocol小于3,则pickle将尝试将新的Python 3名称映射到Python 2中使用的旧模块名称,以便使用Python 2可读取pickle数据流。

例如:

1
2
3
4
5
import pickle
f = open('dump.txt', 'wb')
d = dict(name='Tom', age=10, score=45)
pickle.dump(d, f)   #dict对象序列后写入文件f
f.close()

pickle.dumps(obj, protocol=None, *, fix_imports=True)
参数的意义和dump()一样。
把任意对象序列化成一个bytes对象,而不是序列化成一个文件。序列化后的bytes对象可以写入文件。

例如:

1
2
3
4
5
6
7
import pickle
d = dict(name='Tom', age=10, score=45)
b = pickle.dumps(d)     #dict对象序列化成bytes对象
print(type(d))
print(d)
print(type(b))
print(b)

执行以上程序会输出如下结果:

1
2
3
4
<class 'dict'>
{'name': 'Tom', 'score': 45, 'age': 10}
<class 'bytes'>
b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x03\x00\x00\x00Tomq\x02X\x05\x00\x00\x00scoreq\x03K-X\x03\x00\x00\x00ageq\x04K\nu.'

pickle.load(file, *, fix_imports=True, encoding=“ASCII”, errors=“strict”)
file:读取的文件对象。此文件必须有两个方法,一个采用整数参数的read()方法和一个不需要参数的readline()方法。两种方法都应返回字节。
fix_imports:默认True。pickle将尝试将旧的Python 2名称映射到Python 3中使用的新名称。
encoding:默认ASCII。
errors:默认strict。

从一个file-like Object中直接反序列化出对象。这相当于Unpickler(file).load().

例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import pickle
f1 = open('dump.txt', 'wb')
d1 = dict(name='Tom', age=10, score=45)
pickle.dump(d1, f1)   #dict对象序列后写入文件f
f1.close()

f2 = open('dump.txt', 'rb')
d2 = pickle.load(f2)
f2.close()
print(type(d2))
print(d2)

执行以上程序会输出如下结果:

1
2
<class 'dict'>
{'score': 45, 'age': 10, 'name': 'Tom'}

pickle.loads(bytes_object, *, fix_imports=True, encoding=“ASCII”, errors=“strict”)
参数的意义和load()一样。
把字节对象反序列化出对象。

例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import pickle
d1 = dict(name='Tom', age=10, score=45)
b1 = pickle.dumps(d1)     #dict对象序列化成bytes对象
print(type(d1))
print(d1)
print(type(b1))
print(b1)

d2 = pickle.loads(b1)  #bytes对象反序列化成对象
print(type(d2))
print(d2)

执行以上程序会输出如下结果:

1
2
3
4
5
6
<class 'dict'>
{'score': 45, 'name': 'Tom', 'age': 10}
<class 'bytes'>
b'\x80\x03}q\x00(X\x05\x00\x00\x00scoreq\x01K-X\x04\x00\x00\x00nameq\x02X\x03\x00\x00\x00Tomq\x03X\x03\x00\x00\x00ageq\x04K\nu.'
<class 'dict'>
{'score': 45, 'name': 'Tom', 'age': 10}

json模块

pickle可以很方便地序列化所有对象。不过json作为更为标准的格式,具有更好的可读性(pickle是二进制数据)和跨平台性。是个不错的选择。json模块提供Python对象到JSON格式转换。

json使用的四个函数名和pickle一致。

json.dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)

json.dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)

json.load(fp, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

json.loads(s, *, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import json
d1 = dict(name='Tom', age=10, score=45)
b1 = json.dumps(d1)     #dict对象序列化成json对象
print(type(d1))
print(d1)
print(type(b1))
print(b1)

d2 = json.loads(b1)  #json对象反序列化成对象
print(type(d2))
print(d2)

执行以上程序会输出如下结果:

1
2
3
4
5
6
<class 'dict'>
{'score': 45, 'name': 'Tom', 'age': 10}
<class 'str'>
{"score": 45, "name": "Tom", "age": 10}
<class 'dict'>
{'score': 45, 'name': 'Tom', 'age': 10}

JSON类型与Python类型的对应关系

JSON类型 Python类型
{} dict
[] list
“string” str
1234.56 int或float
true/false True/False
null None

cPickle模块

cPickle是pickle模块的C语言编译版本相对速度更快。


转载请注明本网址。