Python IO编程 序列化
为什么使用序列化?
因为程序运行期间,所有的变量都在内存中。可以随时修改变量,但程序一接触,所占的内存就会被操作系统回收。如果没有把修改后的'Bill'存储到磁盘上,下次重新运行程序,变量又被初始化为'Bob'。
通过将对象序列化,可以将其存储在变量或内存中,可以保存当时的状态,实现生命周期的延长,并在需要时再次将对这个对象读取出来。
什么是序列化和反序列化?
序列化:把变量从内存中变成可存储或传输的过程称之为序列化。
序列化后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上。
反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。
序列化
python 提供了pickle 和 json 模块, 实现序列化和反序列化
pickle:
dumps:将对象序列化为bytes,然后写入文件
loads:反序列化出对象
dump: 直接将对象序列化写入文件
load: 反序列化出对象
序列化 1、pickle.dumps()方法把任意对象序列化成一个bytes,然后,就可以把这个bytes写入文件 2、pickle.dump()直接把对象序列化后写入一个file-like Object |
|
pickle.dumps() |
pickle.dump() |
import pickle |
import pickle |
反序列化 把对象从磁盘读到内存时,可以先把内容读到一个bytes,然后用 1、pickle.loads()方法反序列化出对象 2、也可以直接用pickle.load()方法从一个file-like Object中直接反序列化出对象 |
|
with open('test.txt','rb') as f: |
with open('test.txt','rb') as f: print(pickle.load(f)) |
Json
如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。
JSON和Python内置的数据类型
JSON类型 |
Python类型 |
{} |
dict |
[] |
list |
“string” |
str |
true/false |
True/False |
null |
None |
Python内置的json模块提供了非常完善的Python对象到JSON格式的转换。
转换为Json 1、dumps() :将对象序列化为JSON字符串; 返回一个str,内容是标准的Json 2、dump(): 将对象序列化为JSON字符串,然后写入文件 |
Json反序列化为Python对象
2、 |
import json |
json_str = '{"age": 20, "score": 88, "name": "Bob"}'
|
由于JSON标准规定JSON编码是UTF-8,所以我们总是能正确地在Python的str与JSON的字符串之间转换。 |
JSON进阶:类对象的序列化和反序列化
import json 报错:TypeError: Object of type Student is not JSON serializable 错误的原因是Student对象不是一个可序列化为JSON的对象。 默认情况下,dumps()方法不知道如何将Student实例变为一个JSON的{}对象。 |
可选参数default就是把任意一个对象变成一个可序列为JSON的对象,我们只需要为Student专门写一个转换函数,再把函数传进去即可: def student2dict(std): print(json.dumps(s, default=student2dict)) 不过,下次如果遇到一个Teacher类的实例,照样无法序列化为JSON。我们可以偷个懒,把任意class的实例变为dict: print(json.dumps(s, default=lambda obj: obj.__dict__)) 因为通常class的实例都有一个__dict__属性,它就是一个dict,用来存储实例变量。也有少数例外,比如定义了__slots__的class。 |
同样的道理,如果我们要把JSON反序列化为一个Student对象实例,loads()方法首先转换出一个dict对象,然后,我们传入的object_hook函数负责把dict转换为Student实例: def dict2student(d):
def dict2student(d): |