序列化
把变量从内存中变成可存储或传输的过程称之为序列化, 在Python中叫pickling,在Java中叫serialization,其他语言中也有叫marshalling,flattening等等。
Python提供了pickle
模块实现序列化
import pickle
d = dict(name= 'Bob', age=20, score=88)
pickle.dumps(d)
b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x03\x00\x00\x00Bobq\x02X\x03\x00\x00\x00ageq\x03K\x14X\x05\x00\x00\x00scoreq\x04KXu.'
pickle.dumps()
方法把任意对象序列化成bytes stream。或者通过另一个方法pickle.dump()
把对象序列化后写入一个file-like object:
f = open('dump.txt', 'wb')
pickle.dump(d, f)
f.close()
# 此时dump.txt文件中保存着序列化后二进制存储的一些文件
把对象从磁盘读入内存中,然后用pickle.loads()
方法反序列化出对象,也可以直接用pickle.load()
方法从一个file-like Object中直接反序列化出对象。我们打开另一个Python命令行来反序列化刚才保存的对象:
f = open('dump.txt', 'rb')
d = pickle.load(f)
f.close()
d
{'name': 'Bob', 'age': 20, 'score': 88}
Pickle的问题和所有其他编程语言特有的序列化问题一样,就是它只能用于Python,并且可能不同版本的Python彼此都不兼容,因此,只能用Pickle保存那些不重要的数据,不能成功地反序列化也没关系。
JSON
如果要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML格式,或者JSON格式。Python中的json
模块提供了完善的json格式转换。
import json
d = dict(name='Bob', age=20, score=88)
json.dumps(d)
'{"name": "Bob", "age": 20, "score": 88}'
dumps()
方法返回一个str
,内容就是标准的JSON。类似的,dump()
方法可以直接把JSON写入一个file-like Object
类似,反序列化用loads()
或load()
方法。
json_str = '{"name": "Bob", "age": 20, "score": 88}'
json.loads(json_str)
{'name': 'Bob', 'age': 20, 'score': 88}
JSON进阶
Python中的dict
可以被序列化,但是如果想让定义的class
也能序列化,比如定义的Student
类。
import json
class Student:
def __init__(self, name, age, score):
self.name = name
self.age = age
self.score = score
s = Student('Bob', 20, 88)
# print(json.dumps(s)) # Error
为了解决这个问题,为Student
专门写一个转换函数,把类转换成dict
,再把函数传进去即可
def student2dict(std):
return {
'name': std.name,
'age': std.age,
'score': std.score
}
print(json.dumps(s, default=student2dict))
{"name": "Bob", "age": 20, "score": 88}
也可以把任意的class
的实例变成dict
,但是定义了__slot__
的class不能这么做。
print(json.dumps(s, default=lambda obj: obj.__dict__))
{"name": "Bob", "age": 20, "score": 88}
同样的要把JSON反序列化,json.loads()
方法首先转换出一个dict
,然后在把dict转换成实例
def dict2student(d):
return Student(d['name'], d['age'], d['score'])
json_str = '{"age": 20, "score": 88, "name": "Bob"}'
s2 = json.loads(json_str, object_hook=dict2student)
print(s2.name, s2.age, s2.score)
Bob 20 88
对中文进行序列化时,有一个ensure_ascii
参数。
import json
obj = dict(name='小明', age=20)
s = json.dumps(obj, ensure_ascii=True)
print(s)
s2 = json.dumps(obj, ensure_ascii=False)
print(s2)
{"name": "\u5c0f\u660e", "age": 20}
{"name": "小明", "age": 20}