Python开发之序列化与反序列化:pickle、json模块使用详解

1 引言

  在平常开发中,全部的对象都是存储在内存当中,尤为是像python这样的坚持一切接对象的高级程序设计语言,一旦关机,在写在内存中的数据都将不复存在。另外一方面,存储在内存够中的对象因为编程语言、网络环境等等因素,很难在网络中进行传输交互。由此,就诞生了一种机制,能够实现内存中的对象与方便持久化在磁盘中或在网络中进行交互的数据格式(str、bites)之间的相互转换。这种机制就叫序列化与发序列化:html

  序列化:将内存中的不可持久化和传输对象转换为可方便持久化和传输对象的过程。python

  反序列化:将可持久化和传输对象转换为不可持久化和传输对象的过程。web

  Python中提供pickle和json两个模块来实现序列化与反序列化,pickle模块和json模块dumps()、dump()、loads()、load()这是个函数,其中dumps()、dump()用于实现序列化,loads()、load()用于实现反序列化。下面,咱们分别对pickle和json模块进行介绍。shell

2  pickle模块

  pickle模块的dumps()、dump()、loads()、load()是个函数按功能划分能够分为两组:
  序列化:dumps()、dump()
  反序列化:loads()、load()
   dumps()与dump()的区别是dumps()只是单纯得将对象序列化,而dump()会在序列化以后将结果写入到文件当中;与之对应,loads()与load()区别至于loads()是对dumps的序列化结果进行反序列化,而dump()会从文件中读取内容进行反序列化。

2.1 dumps()与loads()

>>> import pickle >>> p_dict = {'name':'张三' , 'age':30 , 'isMarried':False} # 定义一个字典
>>> p_str = pickle.dumps(p_dict) # 序列化
>>> type(p_dict) <class 'dict'>
>>> type(p_str) <class 'bytes'>
>>> p_str b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x06\x00\x00\x00\xe5\xbc\xa0\xe4\xb8\x89q\x02X\x03\x00\x00\x00ageq\x03K\x1eX\t\x00\x00\x00isMarriedq\x04\x89u.'
>>> p = pickle.loads(p_str) >>> type(p) <class 'dict'>
>>> p {'name': '张三', 'age': 30, 'isMarried': False}
  能够看到,反序列化后获得的p和序列化以前的p_dict内容是如出一辙的。不过,p与p_dict已是两个不一样的对象了:
>>> id(p)==id(p_dict) False

2.2 dump()与load()

  序列化:
>>> import pickle >>> p_dict = {'name':'张三' , 'age':30 , 'isMarried':False} # 定义一个字典
>>> file = open("my_dump.txt", "wb") # 由于序列化只有的是bites类型,因此必须以wb模式打开
>>> pickle.dump(p_dict, file) >>> file.close()
  此时,经过上面代码咱们已经将p_dict序列化成功,并写入到了一个名为my_dump.txt文件中。你能够找到这个文件,而后将它拷贝到任何电脑上进行反序列化:
>>> file=open("my_dump.txt","rb") >>> p=pickle.load(file) >>> file.close() >>> type(p) <class 'dict'>
>>> p {'name': '张三', 'age': 30, 'isMarried': False}
  看,反序列化后获得的内容与序列化以前的内容彻底同样。体会到序列化与反序列化的做用了吗?序列化以后的内容能够方便得保存到磁盘中,电脑关机也不怕。

3 json模块

  若是你阅读并理解了上文中关于pickle的部门内容,对于这一部分的json模块内容,你能够不费吹灰之力掌握。上文中说到过,与pickle同样,json模块也提供了dumps()、dump()、loads()、load()则是个函数,且其中区别也与pickle中是个函数的区别是同样的。

3.1 dumps()与loads()

>>> import pickle >>> p_dict = {'name':'张三' , 'age':30 , 'isMarried':False} # 定义一个字典
>>> import json >>> p_dict = {'name':'张三' , 'age':30 , 'isMarried':False} # 定义一个字典
>>> p_str = json.dumps(p_dict) >>> type(p_str) <class 'str'>
>>> p_str '{"name": "\\u5f20\\u4e09", "age": 30, "isMarried": false}'
  能够看到,json序列化以后获得的是json格式字符串,但上述json字符串中,中文部份内容显示为了“乱码”。怎么办呢? json的dumps()函数(dump()函数也有)中提供了一个ensure_ascii参数,将该参数的值设置为False,可令序列化后中文依然正常显示。
>>> p_str2 = json.dumps(p_dict, ensure_ascii=False) >>> p_str2 '{"name": "张三", "age": 30, "isMarried": false}'
  接着上面的内容进行反序列化:
>>> p1 = json.loads(p_str) >>> p1 {'name': '张三', 'age': 30, 'isMarried': False} >>> p2 = json.loads(p_str) >>> p2 {'name': '张三', 'age': 30, 'isMarried': False}

3.2 dump()与load()

>>> import json >>> p_dict = {'name':'张三' , 'age':30 , 'isMarried':False} # 定义一个字典
>>> file = open('d:/mydump.txt' , 'w') >>> json.dump(p_dict , file) >>> file.close()
  固然,你也能够加上ensure_ascii这一参数,并将其值设置为False,这样你打开mydump.txt文件里面的中文就能正常显示。(执行完代码以后,本地会有一个mydump.txt文件,诸位能够验证该内容)
>>> file = open('d:/mydump.txt' , 'w') >>> json.dump(p_dict , file , ensure_ascii=False) >>> file.close()
  继续反序列化:
>>> file = open('d:/mydump.txt' , 'r') >>> p = json.load(file) >>> file.close() >>> type(p) <class 'dict'>
>>> p {'name': '张三', 'age': 30, 'isMarried': False}
  经过上面内容,pickle和json模块关于序列化与反序列化的操做就介绍完了。咱们能够发现,pickle与json两个模块不管是在函数名,仍是在功能上,都是机器类似的。既然这样,有了pickle模块,为何还有json模块的诞生呢?接下来来讲说pickle与json模块的区别。

4 pickle模块与json模块的区别

   (1)pickle模块用于Python语言特有的类型和用户自定义类型与Python基本数据类型之间的转换
  json模块用于字符串和python数据类型间进行转换。以下所示,咱们自定义一个Person类,分别用pickle和json进行序列化:
>>> class Person: def __init__(self , name , age , isMarried): self.name = name self.age = age self.isMarried = isMarried >>> p = Person('张三' , 30 , False)
  使用pickle模块进行序列化与反序列化:
>>> p = Person('张三' , 30 , False) >>> import pickle >>> pp = pickle.dumps(p) >>> type(pp) <class 'bytes'>
>>> pp b'\x80\x03c__main__\nPerson\nq\x00)\x81q\x01}q\x02(X\x04\x00\x00\x00nameq\x03X\x06\x00\x00\x00\xe5\xbc\xa0\xe4\xb8\x89q\x04X\x03\x00\x00\x00ageq\x05K\x1eX\t\x00\x00\x00isMarriedq\x06\x89ub.'
>>> p2 = pickle.loads(pp) >>> type(p2) <class '__main__.Person'>
>>> p2.name '张三'
  甚至pickle模块还可以对Peron自己进行序列化:
>>> per = pickle.dumps(Person) >>> per b'\x80\x03c__main__\nPerson\nq\x00.'
>>> per2 = pickle.loads(per) >>> per2 <class '__main__.Person'>
  若是用json对Person实例对象进行序列化,就会报错:
>>> import json >>> p = Person('张三' , 30 , False) >>> json.dumps(p) Traceback (most recent call last): File "<pyshell#49>", line 1, in <module> json.dumps(p) …… TypeError: Object of type 'Person' is not JSON serializable
   若是非要用json对Person对象进行序列化,必须先定义一个将Person对象转化为字典(dict)的方法
>>> def person2dict(per): return { 'name':per.name , 'age':per.age , 'isMarried':per.isMarried } >>> p3 = json.dumps(p , default=person2dict) >>> type(p3) <class 'str'>
>>> p3 '{"name": "\\u5f20\\u4e09", "age": 30, "isMarried": false}'
>>> p3 = json.dumps(p , default=person2dict , ensure_ascii=False) >>> type(p3) <class 'str'>
>>> p3 '{"name": "张三", "age": 30, "isMarried": false}'
  固然,也不能直接进行反序列化,否则也只会获得一个字典:
>>> p4 = json.loads(p3) >>> type(p4) <class 'dict'>
>>> p4 {'name': '张三', 'age': 30, 'isMarried': False}
  此时,也要定义一个将字典转换为Person类实例的方法,在进行反序列化:
>>> def dict2person(d): return Person(d['name'],d['age'],d['isMarried']) >>> p5 = json.loads(p3 , object_hook=dict2person) >>> type(p5) <class '__main__.Person'>
>>> p5.name '张三'
  (2)pickle序列化结果为bites类型,只适合于Python机器之间的交互。
    json序列化结果为str类型,可以被多种语言识别,可用于与其余程序设计语言交互。
  目前,JSON格式字符串已经成为网络传输中的一种标准格式,因此在web后台开发中一般用json模块来序列化而不是pickle模块。
   JSON和Python内置的数据类型对应以下:
JSON类型
Python类型
{}
dict
[]
list
"string"
'str'或u'unicode'
1234.56
int或float
true/false
True/False
null
None

5 总结

  (1)序列化与反序列化是为了解决内存中对象的持久化与传输问题;
  (2)Python中提供了pickle和json两个模块进行序列化与反序列化;
  (3)dumps()和dump()用于序列化,loads()和load()用于反序列化;
  (4)pickle模块能序列化任何对象,序列化结果为bites类型,只适合于Python机器之间交互;
  json模块只能序列化Python基本类型,序列化结果为json格式字符串,适合不一样开发语言之间交互。

原文出处:https://www.cnblogs.com/chenhuabin/p/10502096.html编程

相关文章
相关标签/搜索