前言
前面在学习时,简单介绍了Python中的序列化和反序列化。我们已经知道,在程序运行的过程中,所有的变量都是在内存中,比如,定义一个dict:,我们可以随时修改变量的值,比如把改成。但是一旦程序结束,变量所占用的内存就被操作系统全部回收。如果没有把修改后的存储到磁盘上,下次重新运行程序,变量又被初始化为。
今天我们就来系统地学习Python中的序列化和反序列化。
序列化和反序列化
在python中,序列化可以理解为:把python的对象编码转换为json格式的字符串,反序列化可以理解为:把json格式字符串解码为python数据对象。
我们把变量从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等都是一个意思。序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上。反过来,把内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。
在python的标准库中,专门提供了json库与pickle库来处理这部分。
pickle模块
使用pickle模块,首先要导入该模块:
把序列化后的内容存储在变量中
返回结果是序列化后的字节数据。
运行结果:
把序列化后的数据还原为对象(反序列化)
经过上面的序列化后,数据以字节保存在了变量中,需要再次使用的时候使用函数就行了。如下:
运行结果:
直接存储在文件中
上面的方法把任意对象序列化成一个,然后,就可以把这个写入文件。或者用另一个方法直接把对象序列化后写入一个,进行持久化。注意这次用的方法中少了个,即:,而不是上面用到的。
由于pickle写入的是二进制数据,所以打开方式需要以和的模式。
运行结果:
直接把序列化后的内容写入到文件中
也可以直接用方法从一个中直接反序列化出对象。如下:
运行结果:
这样我们的数据就从文件中成功地反序列化到内存,保存到变量中了。要注意的是:这个变量和原来的变量是完全不相干的对象,它们只是内容相同而已。
序列化用户自定义对象
开发中用的最多的就是我们自己定义类的对象,pickle当然也能写入,不仅可以写入类本身,也能写入它的一个实例。
假设我们现在设计了一个类:
将类本身序列化到文件中:
运行结果:
将类本身序列化到文件中
将自定义类从文件中反序列化出来,并创建对象:
运行结果:
接下来,看下如何序列化自定义类的对象:
运行结果:(2处影响):
1.创建了文件,并写入了序列化后的数据到该文件中。
创建了文件,并写入了序列化后的数据
2.打印结果:
从文件中反序列化出对象:
运行结果:
上面演示了pickle模块序列化和反序列化,两套方法:序列化到文件并反序列化到变量的和序列化到文件并反序列化的。
json模块
如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。
提示:本质就是字符串,是一个特殊格式的字符串而已。
JSON表示的对象就是标准的JavaScript语言的对象,JSON和Python内置的数据类型对应如下:
Python内置的json模块提供了非常完善的Python对象到JSON格式的转换。我们先看看如何把Python对象变成一个JSON:
如果您有一个对象x,则可以使用一行简单的代码查看其JSON字符串表示:
运行结果:
提示:
1.使用前要先导入模块,此处是方法,区别于方法。如果你遇到了下面错误,请检查方法是否使用错误:
此文中用的python是3.5,在版本3.6中已更改:所有可选参数现在仅为关键字。
2.方法的另一个变体,只是将对象序列化为文本文件。
dumps()方法返回一个str,内容就是标准的JSON。类似的,dump()方法可以直接把JSON写入一个file-like Object。
要把JSON反序列化为Python对象,用或者对应的方法,前者把JSON的字符串反序列化,后者从中读取字符串并反序列化。
用反序列化
运行结果:
用反序列化
用反序列化,直接将文件反序列化为内存中的对象。
运行结果:
JSON进阶
Python的等对象可以直接序列化为JSON的,不过,很多时候,我们更喜欢用表示对象,比如定义类,然后序列化:
运行结果:
解析:发现报错了,错误的原因是对象不是一个可序列化为的对象。
查看该方法官方文档,此文中用的python是3.5,在版本3.6中已更改:所有可选参数现在仅为关键字。
这些参数就是让我们来定制JSON序列化。前面的代码之所以无法把类实例序列化为,是因为默认情况下,方法不知道如何将实例变为一个的对象。
可选参数就是把任意一个对象变成一个可序列为的对象,我们只需要为专门写一个转换函数,再把函数传进去即可:
我们再进行序列化时,就可以用到该函数了:
运行结果:
不过,下次如果遇到一个类的实例,照样无法序列化为JSON。我们可以偷个懒,把任意class的实例变为dict,我们可以这么干:
之所以可以这么写,是因为通常的实例都有一个属性,它就是一个,用来存储实例变量。要特别注意,也有少数例外,比如定义了的。
同样的道理,如果我们要把反序列化为一个对象实例,方法首先转换出一个对象,然后,我们传入的函数负责把转换为实例:
核心代码:
运行结果:
打印出的是反序列化的实例对象:
以上是存储到变量,存储到文件也是类似操作。
小结
本小节系统地学习了python中如何序列化和反序列化。重点学习python的标准库中的专门提供的:。
领取专属 10元无门槛券
私享最新 技术干货