- Preface 前言
- 第1章 引论
- 第2章 编程惯用法
- 第3章 基础语法
- 建议19:有节制地使用 from…import 语句
- 建议20:优先使用 absolute import 来导入模块
- 建议21:i+=1 不等于 ++i
- 建议22:使用 with 自动关闭资源
- 建议23:使用 else 子句简化循环(异常处理)
- 建议24:遵循异常处理的几点基本原则
- 建议25:避免 finally 中可能发生的陷阱
- 建议26:深入理解 None 正确判断对象是否为空
- 建议27:连接字符串应优先使用 join 而不是 +
- 建议28:格式化字符串时尽量使用 .format 方式而不是 %
- 建议29:区别对待可变对象和不可变对象
- 建议30:[]、() 和 {}:一致的容器初始化形式
- 建议31:记住函数传参既不是传值也不是传引用
- 建议32:警惕默认参数潜在的问题
- 建议33:慎用变长参数
- 建议34:深入理解 str() 和 repr() 的区别
- 建议35:分清 staticmethod 和 classmethod 的适用场景
- 第4章 库
- 建议36:掌握字符串的基本用法
- 建议37:按需选择 sort() 或者 sorted()
- 建议38:使用 copy 模块深拷贝对象
- 建议39:使用 Counter 进行计数统计
- 建议40:深入掌握 ConfigParser
- 建议41:使用 argparse 处理命令行参数
- 建议42:使用 pandas 处理大型 CSV 文件
- 建议43:一般情况使用 ElementTree 解析 XML
- 建议44:理解模块 pickle 优劣
- 建议45:序列化的另一个不错的选择 JSON
- 建议46:使用 traceback 获取栈信息
- 建议47:使用 logging 记录日志信息
- 建议48:使用 threading 模块编写多线程程序
- 建议49:使用 Queue 使多线程编程更安全
- 第5章 设计模式
- 第6章 内部机制
- 建议54:理解 built-in objects
- 建议55:init() 不是构造方法
- 建议56:理解名字查找机制
- 建议57:为什么需要 self 参数
- 建议58:理解 MRO 与多继承
- 建议59:理解描述符机制
- 建议60:区别 getattr() 和 getattribute() 方法
- 建议61:使用更为安全的 property
- 建议62:掌握 metaclass
- 建议63:熟悉 Python 对象协议
- 建议64:利用操作符重载实现中缀语法
- 建议65:熟悉 Python 的迭代器协议
- 建议66:熟悉 Python 的生成器
- 建议67:基于生成器的协程及 greenlet
- 建议68:理解 GIL 的局限性
- 建议69:对象的管理与垃圾回收
- 第7章 使用工具辅助项目开发
- 第8章 性能剖析与优化
建议45:序列化的另一个不错的选择 JSON
JSON(JavaScript Object Notation)是一种轻量级数据交换格式,它基于JavaScript编程语言的一个子集,于1999年12月成为一个完全独立于语言的文本格式。由于其格式使用了其他许多流行编程的约定,如C、C++、C#、Java、JS、Python等,加之其简单灵活、可读性和互操作性较强、易于解析和使用等特点,逐渐变得流行起来,甚至有代替XML的趋势。关于JSON和XML之间的优劣,一直有很多争论,本书并不打算对这两者之间的是是非非做详尽的分析(笔者的观点是两者各有所长,在相当长的时间里还会共存共荣),这里关注的是JSON用于序列化方面的优势。在进行详细讨论之前,我们先来看看Python语言中对JSON的支持现状。
Python中有一系列的模块提供对JSON格式的支持,如simplejson、cjson、yajl、ujson,自Python2.6后又引入了标准库JSON。简单来说cjson和ujson是用C来实现的,速度较快。据cjson的文档表述:其速率比纯Python实现的json模块大概要快250倍。yajl是Cpython版本的JSON实现,而simplejson和标准库JSON本质来说无多大区别,实际上Python2.6中的json模块就是simplejson减去对Python2.4、2.5的支持以充分利用最新的兼容未来的功能。不过相对于simplejson,标准库更新相对较慢,Python2.7.5中simplejson对应的版本为2.0.9,而最新的simplejson的版本为3.3.0。在实际应用过程中将这两者结合较好的做法是采用如下import方法。
try: import simplejson as json except ImportError: import json
本节仍采用标准库JSON来做一些探讨。Python的标准库JSON提供的最常用的方法与pickle类似,dump/dumps用来序列化,load/loads用来反序列化。需要注意的json默认不支持非ASCII-based的编码,如load方法可能在处理中文字符时不能正常显示,则需要通过encoding参数指定对应的字符编码。在序列化方面,相比pickle,JSON具有以下优势:
1)使用简单,支持多种数据类型。JSON文档的构成非常简单,仅存在以下两大数据结构。
名称/值对的集合。在各种语言中,它被实现为一个对象、记录、结构、字典、散列表、键列表或关联数组。
值的有序列表。在大多数语言中,它被实现为数组、向量、列表或序列。在Python中对应支持的数据类型包括字典、列表、字符串、整数、浮点数、True、False、None等。JSON中数据结构和Python中的转换并不是完全一一对应,存在一定的差异,读者可以自行查阅文档。Python中一个JSON文档可以分解为如图4-3所示形式。
2)存储格式可读性更为友好,容易修改。相比于pickle来说,json的格式更加接近程序员的思维,修改和阅读上要容易得多。dumps()函数提供了一个参数indent使生成的json文件可读性更好,0意味着“每个值单独一行”;大于0的数字意味着“每个值单独一行并且使用这个数字的空格来缩进嵌套的数据结构”。但需要注意的是,这个参数是以文件大小变大为代价的。如图4-4展示的是这两种格式之间的对比,其中json.dumps()使用了indent参数输出。
3)json支持跨平台跨语言操作,能够轻易被其他语言解析,如Python中生成的json文件可以轻易使用JavaScript解析,互操作性更强,而pickle格式的文件只能在Python语言中支持。此外json原生的JavaScript支持,客户端浏览器不需要为此使用额外的解释器,特别适用于Web应用提供快速、紧凑、方便的序列化操作。此外,相比于pickle,json的存储格式更为紧凑,所占空间更小。
图4-3 json文档分解图
图4-4 pickle和json文件格式对比
4)具有较强的扩展性。json模块还提供了编码(JSONEncoder)和解码类(JSONDecoder)以便用户对其默认不支持的序列化类型进行扩展。来看一个例子:
>>> d=datetime.datetime.now() >>> d datetime.datetime(2013, 9, 15, 8, 54, 59, 851000) >>> json.dumps(d) ... ... ... raise TypeError(repr(o) + " is not JSON serializable") TypeError: datetime.datetime(2013, 9, 15, 8, 54, 59, 851000) is not JSON seriali zable
5)json在序列化datetime的时候会抛出TypeError异常,这是因为json模块本身不支持datetime的序列化,因此需要对json本身的JSONEncoder进行扩展。有多种方法可以实现,下面的例子是其中实现之一。
import datetime from time import mktime try: import simplejson as json except ImportError: import json class DateTimeEncoder(json.JSONEncoder): # 对JSONEncoder 进行扩展 def default(self, obj): if isinstance(obj, datetime.datetime): return obj.strftime('%Y-%m-%d %H:%M:%S') elif isinstance(obj, date): return obj.strftime('%Y-%m-%d') return json.JSONEncoder.default(self, obj) d=datetime.datetime.now() print json.dumps(d, cls = DateTimeEncoder) # 使用cls 指定编码器的名称
最后需要提醒的是,Python中标准模块json的性能比pickle与cPickle稍逊。如果对序列化性能要求非常高的场景,可以选择cPickle模块。图4-5显示的是这三者序列化时随着数据规模增加所消耗时间改变的图例。
图4-5 pickle、json、cPickle序列化文件时性能比较
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论