深入Python3 (Dive Into Python3)笔记13--序列化python对象

本文介绍Python中数据持久化的几种方法,包括使用pickle模块保存复杂数据结构到二进制文件,以及利用JSON进行跨语言兼容的数据交换。文中还探讨了pickle和JSON在序列化过程中的差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一切内容都是摘抄,主要是便于回忆和鼓励自己不要间断,更详细内容请见原帖地址:

《深入 python3 》中文版

http://woodpecker.org.cn/diveintopython3/index.html

无关课程的内容,自己研究的部分

可选的有:shelve, pickle, anydbm, JSON

anydbm允许我们将一个磁盘上的文件与一个“dict-like”对象关联起来,操作这个“dict-like”对象,就像操作dict对象一样,最后可以将“dict-like”的数据持久化到文件。对这个"dict-like"对象进行操作的时候,key和value的类型必须是字符串。

shelve模块是anydbm的增强版,它支持在"dict-like"对象中存储任何可以被pickle序列化的对象,但key也必须是字符串。

shelve = pickle + anydbm

 

13.1. 深入

什么东西能用pickle 模块存储?

  • 所有Python支持的 原生类型 : 布尔, 整数, 浮点数, 复数, 字符串, bytes (字节串)对象, 字节数组, 以及 None .
  • 由任何原生类型组成的列表,元组,字典和集合。
  • 由任何原生类型组成的列表,元组,字典和集合组成的列表,元组,字典和集合(可以一直嵌套下去,直至Python支持的最大递归层数 ).
  • 函数,类,和类的实例(带警告)。

13.1.1. 本章例子的快速笔记

13.2. 保存数据到 Pickle 文件

>>> 

shell1


>>> 

import pickle


>>> 

with open('entry.pickle', 'wb') as f:... 

pickle.dump(entry, f)... 


		

 

  • pickle 模块接受一个Python数据结构并将其保存的一个文件。
  • 要做到这样,它使用一个被称为“pickle协议”的东西序列化 该数据结构。
  • pickle 协议是Python特定的,没有任何跨语言兼容的保证。你很可能不能使用Perl, PHP , Java, 或者其他语言来对你刚刚创建的entry.pickle 文件做任何有用的事情。
  • 并非所有的Python数据结构都可以通过pickle 模块序列化。随着新的数据类型被加入到Python语言中,pickle协议已经被修改过很多次了,但是它还是有一些限制。
  • 由于这些变化,不同版本的Python的兼容性也没有保证。新的版本的Python支持旧的序列化格式,但是旧版本的Python不支持新的格式(因为它们不支持新的数据类型)。
  • 除非你指定,pickle 模块中的函数将使用最新版本的pickle协议。这保证了你对可以被序列化的数据类型有最大的灵活度,但这也意味着生成的文件不能被不支持新版pickle协议的旧版本的Python读取。
  • 最新版本的pickle协议是二进制格式的。请确认使用二进制模式来打开你的pickle文件,否则当你写入的时候数据会被损坏。

 

13.3. 从Pickle文件读取数据

pickle.dump() / pickle.load()循环的结果是一个和原始数据结构等同的新的数据结构。

13.4. 不使用文件来进行序列化

  1. pickle.dumps() 函数(注意函数名最后的's' )执行和pickle.dump() 函数相同的序列化。取代接受流对象并将序列化后的数据保存到磁盘文件,这个函数简单的返回序列化的数据。
  2. 由于pickle协议使用一个二进制数据格式,所以pickle.dumps() 函数返回bytes 对象。
  3. pickle.loads() 函数(再一次, 注意函数名最后的's' ) 执行和pickle.load() 函数一样的反序列化。取代接受一个流对象并去文件读取序列化后的数据,它接受包含序列化后的数据的bytes 对象, 比如pickle.dumps() 函数返回的对象。

13.5. 字节串和字符串又一次抬起了它们丑陋的头。

13.6. 调试Pickle 文件

import pickletools

13.7. 序列化Python对象以供其它语言读取

pickle 模块使用的数据格式是Python特定的。它没有做任何兼容其它编程语言的努力。如果跨语言兼容是你的需求之一,你得去寻找其它的序列化格式。一个这样的格式是 JSON 。 “JSON ” 代表 “JavaScript Object Notation,” 但是不要让名字糊弄你。 — JSON 是被设计为跨语言使用的。

Python 3 在标准库中包含了一个 json 模块。同 pickle 模块类似, json 模块包含一些函数,可以序列化数据结构,保存序列化后的数据至磁盘,从磁盘上读取序列化后的数据,将数据反序列化成新的Pythone对象。但两者也有一些很重要的区别。 首先, JSON 数据格式是基于文本的, 不是二进制的。RFC 4627 定义了JSON 格式以及怎样将各种类型的数据编码成文本。比如,一个布尔值要么存储为5个字符的字符串'false' ,要么存储为4个字符的字符串 'true' 。 所有的JSON 值都是大小写敏感的。

第二,由于是文本格式, 存在空白(whitespaces)的问题。 JSON 允许在值之间有任意数目的空白(空格, 跳格, 回车,换行)。空白是“无关紧要的”,这意味着JSON 编码器可以按它们的喜好添加任意多或任意少的空白, 而JSON 解码器被要求忽略值之间的任意空白。这允许你“美观的打印(pretty-print)” 你的 JSON 数据, 通过不同的缩进层次嵌套值,这样你就可以在标准浏览器或文本编辑器中阅读它。Python 的 json 模块有在编码时执行美观打印(pretty-printing)的选项。

第三, 字符编码的问题是长期存在的。JSON 用纯文本编码数据, 但是你知道, “不存在纯文本这种东西。” JSON 必须以Unicode 编码(UTF-32, UTF-16, 或者默认的, UTF-8 )方式存储, RFC 4627的第3节 定义了如何区分使用的是哪种编码。

13.8. 将数据保存至 JSON 文件

import json
with open('basic.json', mode='w', encoding='utf-8') as f:
json.dump(basic_entry, f)

json.dump(basic_entry, f, indent=2)

如果你给json.dump()函数传入indent参数, 它以文件变大为代价使生成的JSON文件更可读。indent 参数是一个整数。0 意味着“每个值单独一行。” 大于0的数字意味着“每个值单独一行并且使用这个数目的空格来缩进嵌套的数据结构。”

13.9. 将Python数据类型映射到JSON

注意到什么被遗漏了吗?元组和 & 字节串(bytes)! JSON 有数组类型, json 模块将其映射到Python的列表, 但是它没有一个单独的类型对应 “冻结数组(frozen arrays)” (元组)。而且尽管 JSON 非常好的支持字符串,但是它没有对bytes 对象或字节数组的支持。

13.10. 序列化JSON不支持的数据类型

即使JSON没有内建的字节流支持, 并不意味着你不能序列化bytes对象。json模块提供了编解码未知数据类型的扩展接口。(“未知”的意思是?JSON没有定义”。很显然json 模块认识字节数组, 但是它被JSON规范的限制束缚住了。) 如果你希望编码字节串或者其它JSON没有原生支持的数据类型,你需要给这些类型提供定制的编码和解码器。

以下内容略看,具体情况用到再看教材吧

13.11. 从JSON文件加载数据

但是重现创建的entry2 数据结构中, 'tags' 键的值是一个三个字符串组成的列表。JSON 并不区分元组和列表;它只有一个类似列表的数据类型,数组,并且json模块在序列化过程中会安静的将元组和列表两个都转换成JSON 数组。大多数情况下,你可以忽略元组和列表的区别,但是在使用json 模块时应记得有这么一回使。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值