这是有关序列化和反序列化 Python 对象的教程的第二部分。在第一部分中,您学习了基础知识,然后深入研究了 Pickle 和 JSON 的细节。
在这一部分中,您将探索 YAML(确保拥有第一部分中的运行示例),讨论性能和安全注意事项,了解其他序列化格式,最后了解如何选择正确的方案。 p>
YAML
YAML 是我最喜欢的格式。它是一种人性化的数据序列化格式。与 Pickle 和 JSON 不同,它不是 Python 标准库的一部分,因此您需要安装它:
pip 安装 yaml
yaml模块只有load()
和dump()
函数。默认情况下,它们使用像 loads()
和 dumps()
这样的字符串,但可以采用第二个参数,它是一个开放流,然后可以转储/加载到/来自文件。
import yaml print yaml.dump(simple) boolean: true int_list: [1, 2, 3] none: null number: 3.44 text: string
请注意 YAML 与 Pickle 甚至 JSON 相比的可读性。现在是 YAML 最酷的部分:它理解 Python 对象!无需自定义编码器和解码器。以下是使用 YAML 的复杂序列化/反序列化:
> serialized = yaml.dump(complex) > print serialized a: !!python/object:__main__.A simple: boolean: true int_list: [1, 2, 3] none: null number: 3.44 text: string when: 2016-03-07 00:00:00 > deserialized = yaml.load(serialized) > deserialized == complex True
如您所见,YAML 有自己的符号来标记 Python 对象。输出仍然非常容易阅读。日期时间对象不需要任何特殊标记,因为 YAML 本质上支持日期时间对象。
性能
在开始考虑性能之前,您需要考虑性能是否是一个问题。如果您相对不频繁地序列化/反序列化少量数据(例如在程序开始时读取配置文件),那么性能并不是真正的问题,您可以继续前进。
但是,假设您分析了系统并发现序列化和/或反序列化导致性能问题,则需要解决以下问题。
性能有两个方面:序列化/反序列化的速度有多快,以及序列化表示有多大?
为了测试各种序列化格式的性能,我将创建一个较大的数据结构,并使用 Pickle、YAML 和 JSON 对其进行序列化/反序列化。 big_data
列表包含 5,000 个复杂对象。
big_data = [dict(a=simple, when=datetime.now().replace(microsecond=0)) for i in range(5000)]
泡菜
我将在这里使用 IPython,因为它有方便的 %timeit
魔术函数来测量执行时间。
import cPickle as pickle In [190]: %timeit serialized = pickle.dumps(big_data) 10 loops, best of 3: 51 ms per loop In [191]: %timeit deserialized = pickle.loads(serialized) 10 loops, best of 3: 24.2 ms per loop In [192]: deserialized == big_data Out[192]: True In [193]: len(serialized) Out[193]: 747328
默认pickle需要83.1毫秒进行序列化,29.2毫秒进行反序列化,序列化大小为747,328字节。
让我们尝试使用最高协议。
In [195]: %timeit serialized = pickle.dumps(big_data, protocol=pickle.HIGHEST_PROTOCOL) 10 loops, best of 3: 21.2 ms per loop In [196]: %timeit deserialized = pickle.loads(serialized) 10 loops, best of 3: 25.2 ms per loop In [197]: len(serialized) Out[197]: 394350
有趣的结果。序列化时间缩短至仅 21.2 毫秒,但反序列化时间略有增加,达到 25.2 毫秒。序列化大小显着缩小至 394,350 字节 (52%)。
JSON
In [253] %timeit serialized = json.dumps(big_data, cls=CustomEncoder) 10 loops, best of 3: 34.7 ms per loop In [253] %timeit deserialized = json.loads(serialized, object_hook=decode_object) 10 loops, best of 3: 148 ms per loop In [255]: len(serialized) Out[255]: 730000
好的。编码方面的性能似乎比 Pickle 差一点,但解码方面的性能却差很多很多:慢了 6 倍。这是怎么回事?这是 object_hook
函数的一个工件,需要为每个字典运行以检查是否需要将其转换为对象。不使用对象挂钩运行速度要快得多。
%timeit deserialized = json.loads(serialized) 10 loops, best of 3: 36.2 ms per loop
这里的教训是,在序列化和反序列化为 JSON 时,请仔细考虑任何自定义编码,因为它们可能会对整体性能产生重大影响。
YAML
In [293]: %timeit serialized = yaml.dump(big_data) 1 loops, best of 3: 1.22 s per loop In[294]: %timeit deserialized = yaml.load(serialized) 1 loops, best of 3: 2.03 s per loop In [295]: len(serialized) Out[295]: 200091
好的。 YAML 真的非常非常慢。但是,请注意一些有趣的事情:序列化大小仅为 200,091 字节。比 Pickle 和 JSON 都好得多。让我们快速了解一下内部:
In [300]: print serialized[:211] - a: &id001 boolean: true int_list: [1, 2, 3] none: null number: 3.44 text: string when: 2016-03-13 00:11:44 - a: *id001 when: 2016-03-13 00:11:44 - a: *id001 when: 2016-03-13 00:11:44
YAML 在这里非常聪明。它确定所有 5,000 个字典共享相同的“a”键值,因此它仅存储一次并使用 *id001
为所有对象引用它。
安全
安全性通常是一个关键问题。 Pickle和YAML由于构造Python对象,很容易受到代码执行攻击。格式巧妙的文件可以包含将由 Pickle 或 YAML 执行的任意代码。无需惊慌。这是设计使然,并记录在 Pickle 的文档中:
警告:pickle 模块并非旨在防止错误或恶意构建的数据。切勿取消从不受信任或未经身份验证的来源收到的数据。
以及 YAML 文档中的内容:
警告:使用从不受信任的来源收到的任何数据调用 yaml.load 是不安全的! yaml.load 与 pickle.load 一样强大,因此可以调用任何 Python 函数。
您只需要了解,不应使用 Pickle 或 YAML 加载从不受信任的来源收到的序列化数据。 JSON 没问题,但是如果您有自定义编码器/解码器,那么您也可能会暴露。
yaml 模块提供了 yaml.safe_load()
函数,该函数仅加载简单的对象,但随后您会失去很多 YAML 的功能,并且可能选择只使用 JSON。
其他格式
还有许多其他可用的序列化格式。以下是其中的一些。
协议缓冲区
Protobuf(即协议缓冲区)是 Google 的数据交换格式。它是用 C++ 实现的,但具有 Python 绑定。它具有复杂的架构并有效地打包数据。非常强大,但不太容易使用。
消息包
MessagePack 是另一种流行的序列化格式。它也是二进制且高效的,但与 Protobuf 不同的是它不需要模式。它有一个类似于 JSON 的类型系统,但更丰富一些。键可以是任何类型,不仅支持字符串和非 UTF8 字符串。
CBOR
CBOR 代表简洁二进制对象表示。同样,它支持 JSON 数据模型。 CBOR 不像 Protobuf 或 MessagePack 那样出名,但它很有趣,原因有两个:
- 它是官方互联网标准:RFC 7049。
- 它专为物联网 (IoT) 设计。
如何选择?
这是一个大问题。这么多选择,你如何选择?让我们考虑一下应该考虑的各种因素:
- 序列化格式应该是人类可读和/或人类可编辑的吗?
- 是否会从不受信任的来源接收序列化内容?
- 序列化/反序列化是性能瓶颈吗?
- 序列化数据是否需要与非Python环境交换?
我会让您变得非常简单,并介绍几种常见场景以及我为每种场景推荐的格式:
自动保存Python程序的本地状态
此处使用 pickle (cPickle) 和 HIGHEST_PROTOCOL
。它快速、高效,无需任何特殊代码即可存储和加载大多数 Python 对象。它也可以用作本地持久缓存。
配置文件
绝对是 YAML。对于人类需要阅读或编辑的任何内容来说,没有什么比它的简单性更好的了。它已被 Ansible 和许多其他项目成功使用。在某些情况下,您可能更喜欢使用直接的 Python 模块作为配置文件。这可能是正确的选择,但它不是序列化,它实际上是程序的一部分,而不是单独的配置文件。
Web API
JSON 显然是这里的赢家。如今,Web API 最常由原生使用 JSON 的 JavaScript Web 应用程序使用。某些 Web API 可能会返回其他格式(例如,用于密集表格结果集的 csv),但我认为您可以以最小的开销将 csv 数据打包为 JSON(无需将每一行作为具有所有列名称的对象重复)。
高容量/低延迟大规模通信
使用二进制协议之一:Protobuf(如果需要架构)、MessagePack 或 CBOR。运行您自己的测试来验证每个选项的性能和代表能力。
结论
Python对象的序列化和反序列化是分布式系统的一个重要方面。您不能直接通过网络发送 Python 对象。您经常需要与用其他语言实现的其他系统进行互操作,有时您只想将程序的状态存储在持久存储中。
Python 在其标准库中附带了多种序列化方案,还有更多序列化方案可作为第三方模块使用。了解所有选项以及每个选项的优缺点将使您能够选择最适合您情况的方法。
以上是Python 对象序列化和反序列化:第 2 部分的详细内容。更多信息请关注PHP中文网其他相关文章!

2小时内可以学会Python的基本编程概念和技能。1.学习变量和数据类型,2.掌握控制流(条件语句和循环),3.理解函数的定义和使用,4.通过简单示例和代码片段快速上手Python编程。

Python在web开发、数据科学、机器学习、自动化和脚本编写等领域有广泛应用。1)在web开发中,Django和Flask框架简化了开发过程。2)数据科学和机器学习领域,NumPy、Pandas、Scikit-learn和TensorFlow库提供了强大支持。3)自动化和脚本编写方面,Python适用于自动化测试和系统管理等任务。

两小时内可以学到Python的基础知识。1.学习变量和数据类型,2.掌握控制结构如if语句和循环,3.了解函数的定义和使用。这些将帮助你开始编写简单的Python程序。

如何在10小时内教计算机小白编程基础?如果你只有10个小时来教计算机小白一些编程知识,你会选择教些什么�...

使用FiddlerEverywhere进行中间人读取时如何避免被检测到当你使用FiddlerEverywhere...

Python3.6环境下加载Pickle文件报错:ModuleNotFoundError:Nomodulenamed...

如何解决jieba分词在景区评论分析中的问题?当我们在进行景区评论分析时,往往会使用jieba分词工具来处理文�...

如何使用正则表达式匹配到第一个闭合标签就停止?在处理HTML或其他标记语言时,常常需要使用正则表达式来�...


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

VSCode Windows 64位 下载
微软推出的免费、功能强大的一款IDE编辑器

SublimeText3 英文版
推荐:为Win版本,支持代码提示!

禅工作室 13.0.1
功能强大的PHP集成开发环境

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)