pickle/json 序列化 - 交互式学Python | 莫烦Python

pickle/json 序列化

作者: 莫烦 编辑: 莫烦 2021-05-10

文件系统,机器学习,大数据等,都少不了数据文件。Python 也提供了一些比较方便序列化的存储的组件。 什么是序列化(Serialization)呢,说简单也简单,就是把像字典,列表这类的数据,打包保存在电脑硬盘中。 如果粗略的理解对比,就有点像 zip 和 unzip 的过程。

在这一节主要涉及到的功能:

  • Pickle
    • pickle.dumps()
    • pickle.dump()
    • pickle.load()
  • Json
    • json.dumps()
    • json.dump()
    • json.load()

Pickle

我在什么时候会想到要用 pickle 呢?就是我想要把一整个 class 都打包的时候,我会想起要用 pickle。 但是用 pickle 打包 class 是一件有风险的事情,有时候还会失败。我们在后面一点来看看哪些时候会失败,我们又怎么避免打包失败。

下面,我们先来看看一个最简单的例子,怎么把一个字典打包到 pickle 里,打包以后又是什么样子?

如果你点击了运行,你可以看到这个字典被 pickle 以后,已经面目全非,你不能直接读出来里面的信息,因为这些信息已经被编码了。 所以当你在用 pickle 的时候另外一点重要的是,你需不需要能看懂被打包的数据,如果没有这个需求,那你就可以用 pickle, 不然我们后面还会介绍一个叫 json 的打包库,它打出来的包,就是你能看懂的东西了。

好,前面我们只是让 data 变成一串编码字节,下面我们可以用 pickle.dump() 将字典直接转换成一个文件。

光存下来肯定没意思,我们还的在另外一个时刻,将文件读出来。pickle.load() 就能帮上忙。 我们用 open 的方式把文件都读出来,然后再用 pickle 对其解析,还原成最开始的那一个字典。

除了常见的字典,列表,元组这类的数据,pickle 甚至都可以打包 Python 的功能以及类。打包功能的意义我觉得并不是很大, 但是能打包类还是比较有意思的。比如我有一个文件系统,我定义了一个 File 类,而且基于它生成了很多 file 实例。 这些实例都是可以被 pickle 的。

注意,在反序列化 unpickle 的时候,这个 File 的 class 一定要有,不然反序列化会因为找不到 File 类而失败的。 这比较好理解,就是按模具重组原件,你没有这个 File class 模具,pickle 的原件也没有一个模具能够组装起来。

你看最后,unpickle 出来的东西还是一个 class 的实例。你可以按正常的 class 方式使用这个 unpickle 的东西。

有些类型的对象是不能被序列化的。这些通常是那些依赖外部系统状态的对象, 比如打开的文件,网络连接,线程,进程,栈帧等等。 如果你在 class 中把上述东西赋值到了 class 的属性上,比如下面的 self.file = open(),这样的 class 在 pickle 的时候会报错的。

如果你硬要用 pickle 保存,我们也还是有解决方案的。 用户自定义类可以通过提供 __getstate__()__setstate__() 方法来绕过 pickle 的这些限制。 pickle.dump() 会调用 __getstate__() 获取序列化的对象。 __setstate__() 在反序列化时被调用。

pickle 我们就说这么多,相信你已经大概知道了如何使用它。我们下面来看看另一种好用的序列化工具,并介绍一下它的特点。

Json

json 和 pickle 很像。如果有一定编程基础的同学,会一眼看出,json 不是一种数据格式吗?怎么就变成一个 Python 库了? 没错,Python 中的 json 库,就是来处理 json 形式的数据的。

什么是 json 数据?一般来说,Python 里的字典,列表都可以是 json 数据格式。如果我们用 Python 里的 json 库来读一个 Python 字典, 会处理成什么样呢?

其实也没变成什么稀奇古怪的样子,就是照搬字典的样子,变成了一个字符串形式的字典。没错,这就是 json 数据啦。 在网页请求中,我们经常会使用到这样的 json 数据。

如果我们在 Python 中,需要这样明文来存储数据的话,使用 json.dump(),和 pickle.dump() 非常像的方式就好了。

但是 json 相比 pickle 还是有它不及的点。我们上面已经看到,pickle 可以很轻松的打包 Python 的 class。 但是 json 不能序列化保存 class。你只能挑出来重要的信息,放到字典或列表里,然后再用 json 打包字典。 下面就是一段 json 打包 class 会报错的代码。

Pickle 和 Json 的不同

上面说了挺多的,你可能也比较难一次性消化。这不,我给你做一张表,你就能轻松对比这两种方法的异同之处啦。

对比 Pickle Json
存储格式 Python 特定的 Bytes 格式 通用 JSON text 格式,可用于常用的网络通讯中
数据种类 类,功能,字典,列表,元组等 基本和 Pickle 一样,但不能存类,功能
保存后可读性 不能直接阅读 能直接阅读
跨语言性 只能用在 Python 可以跨多语言读写
处理时间 长(需编码数据) 短(不需编码)
安全性 不安全(除非你信任数据源) 相对安全

降低知识传递的门槛

莫烦很常从互联网上学习知识,开源分享的人是我学习的榜样。 他们的行为也改变了我对教育的态度: 降低知识传递的门槛免费 奉献我的所学正是受这种态度的影响。 通过 【赞助莫烦】 能让我感到认同,我也更有理由坚持下去。