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
d = dict(name='Andy',age=18)
byt = pickle.dumps(d)
with open('test.txt','wb') as f:
    f.write(byt)

import  pickle
d = dict(name='Andy',age=18)
with open('test.txt','wb') as f:
    pickle.dump(d,f)

反序列化 

把对象从磁盘读到内存时,可以先把内容读到一个bytes,然后用

1、pickle.loads()方法反序列化出对象

2、也可以直接用pickle.load()方法从一个file-like Object中直接反序列化出对象

 

with open('test.txt','rb') as f:
    byts = f.read()
    print(pickle.loads(byts))
    #{'name': 'Andy', 'age': 18}

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

1、loads() :把JSON的字符串反序列化

2、load()  :从文件中读取字符串并反序列化

import json
d = dict(name='Bob', age=20, score=88)
print(json.dumps(d))
#'{"age": 20, "score": 88, "name": "Bob"}'

json_str = '{"age": 20, "score": 88, "name": "Bob"}'
print(json.loads(json_str))
# {'age': 20, 'score': 88, 'name': 'Bob'}

 

由于JSON标准规定JSON编码是UTF-8,所以我们总是能正确地在Python的str与JSON的字符串之间转换。

JSON进阶:类对象的序列化和反序列化

import json
class Student(object):
    def __init__(self, name, age, score):
        self.name = name
        self.age = age
        self.score = score

s = Student('Bob', 20, 88)
print(json.dumps(s))

报错:TypeError: Object of type Student is not JSON serializable

错误的原因是Student对象不是一个可序列化为JSON的对象。

默认情况下,dumps()方法不知道如何将Student实例变为一个JSON的{}对象。

可选参数default就是把任意一个对象变成一个可序列为JSON的对象,我们只需要为Student专门写一个转换函数,再把函数传进去即可:

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}

不过,下次如果遇到一个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):
    return Student(d['name'], d['age'], d['score'])

 

def dict2student(d):
    return Student(d['name'], d['age'], d['score'])

json_str = '{"age": 20, "score": 88, "name": "Bob"}'
print(json.loads(json_str, object_hook=dict2student))
# <__main__.Student object at 0x10cd3c190>

posted @ 2019-08-23 10:40  猪快跑  阅读(146)  评论(0编辑  收藏  举报