python datetime需要安装_Python 基本功: 5. 数据序列化

84bf94d5fdadb06ce587415a40258bbc.png

这篇文章紧接着前篇:

多多教Python:Python 基本功: 4. 读写文件​zhuanlan.zhihu.com
e4d136dee95d9d4708ed38939ba85ccd.png

仔细阅读的小伙伴会发现,在基本功4 里最后的一个示例中,我们读取解析了文件中的内容,并且把其中的日期,价格金融数据存入了 Python 字典当中:

In[4] abc_dict
Out[4]:{datetime.datetime(2019, 7, 18, 0, 0): 9682.24,
        datetime.datetime(2019, 7, 17, 0, 0): 9411.61,
        datetime.datetime(2019, 7, 16, 0, 0): 10858.7,
        datetime.datetime(2019, 7, 15, 0, 0): 10195.0,
        datetime.datetime(2019, 7, 14, 0, 0): 11378.23,
        datetime.datetime(2019, 7, 13, 0, 0): 11810.0,
        datetime.datetime(2019, 7, 12, 0, 0): 11338.9,
        datetime.datetime(2019, 7, 11, 0, 0): 12090.99,
        datetime.datetime(2019, 7, 10, 0, 0): 12577.85}

我们知道了如何从文章读取数据,解析,保存 (原数据),但是我们该如何保存 abc_dict 这个字典呢?这篇文章通过对数据的序列化,和其更高层次的应用,来了解我们如何正确的对 Python 数据类做存储。

教程需求:

  • Mac OS (Windows, Linux 会略有不同)
  • 安装了 Python 3.0 版本以上, Anaconda
  • 阅读了 多多教Python:Python 基本功: 4. 读写文件

数据序列化

首先我们来了解一下什么是数据序列化。序列化 (Serialization),是指把程序中的一个类转化成一个标准化的格式。标准化的意义是这个格式可以跨程序,跨平台的被使用,而且保持其原有的内容,规范。

首先我们举个例子,在不用数据序列化的方法,而是直接把字典 abc_dict 存入文件,则是下面的情况:

In [1]:save_file = "abc_dict.txt"
In [2]:with open(save_file, 'w') as file_to_write:
           file_to_write.write(str(abc_dict))
  1. 创建一个变量,定义要存入文件名称。
  2. 首先把字典转化成 Python 基础字符串,因为字典本身不能直接被写入文件,然后再把字符串写入文件中。

运行之后,我们会在本地找到一个新的文件,如果你打开的话就是这样:

60e7ad84721bf92d08339ee0990ba16f.png
abc_dict.txt

我们来专业的分析一下这么做的几个问题:

  1. 一致性:保存在文件的是一个字符串,当你再次读取的时候,你需要再次做文件解析,并且没有任何保证解析出来的和保存的内容是一样的。
  2. 有效性:数据非常冗长,原本日期 7/18/2019 变成了 datetime.datetime(2019, 7, 18, 0, 0) 这么一个字符串。在跨平台使用时,占用了过多的内存和网络资源。
  3. 兼容性:文件是 .txt 格式,没有一个标准来定义该如何读取里面的内容。虽然在写入的时候是 Python 字典转化的,但是读取的程序如果不是 Python,或者不存入字典,就会出现 兼容性问题。

保持数据传输的 一致性,有效性,兼容性 就是数据序列化的意义,下面介绍在数据流 (Data Flow)中,两个数据序列化的应用:

8d21bc505abb99fd0de33b6be5a94b3e.png
你的程序需要和其他程序交流,例如 平台 API, 网页请求

f308a9afe6d6e75607463c95b1c3b048.png
串行任务流,每一个任务结束之后数据通过序列化传递到下一个任务。

JSON 序列化

这里我们来介绍第一个序列化方式:JSON。JSON 是一个文件格式,也是一个标准化的数据传输方案,通常网站的后端和前段的交流,移动 APP 和云服务器的交流方式都是通过 JSON。所以我们先来看这个比较通用流行的方法:

In [1]:import json
In [2]:simple_dict = {'ticker': 'baba', 'price': '120.5'}
In [3]:with open('simple_dict.txt', 'w') as file_to_write:
           json.dump(simple_dict, file_to_write)
  1. 第一行调用了 Json 模块 (模块是较小的库,可以理解为子库),Json 不是一个 Python 自带的基本类型,所以需要调用,但是默认都已经装好了。
  2. 创建一个简单字典。
  3. 用同样的方法 With 语境,创建一个 simple_dict.txt 文件来保存数据,然后通过调用 json.dump() 方法,把字典转化成 Json 格式的字符串,然后写进文件。

现在我们打开 simple_dict.txt 的文件,就可以看到里面的数据是通过 Json 格式保存。你可以建立一个更加复杂的字典来更加明了的发现 Json 格式转化后的区别:

In [1]: complex_dict = {'ticker': ['baba', 'pdd'], 'price': {'open': 120, 'close': 123, 'vwap': 122}}

然后用同样的方法保存,打开保存的文件,复制里面的内容,然后进入:

Json Parser Online​json.parser.online.fr

一个 Json 在线解析网站,黏贴 Json 内容,就会发现解析过后的字符串显示的非常清晰。

从 Python 中读取我们保存下来的 simple_dict 很简单,只需要一行代码:

In [1]:with open('simple_dict.txt', 'r') as file_to_read:
           loaded_simple_dict = json.load(file_to_read)
           print(type(loaded_simple_dict))
Out [1]: <class 'dict'>
  1. json.load() 是直接从文件中读取全部字符串,然后转化成 Json 理解的格式,然后传给变量 loaded simple dict。看了一下这个变量,的确是字典类。

那 Json 方法有什么弊端呢?尝试把之前创建的 abc_dict 这个字典用同样的方法保存进文件中,你们会发现 Python 会报错:

cc394fc6565c249751b348094d623a1d.png

这个错是因为 abc_dict 字典里的 钥匙是 Python 的 Datetime 数据类,而 Json 的标准化里面并没有 Python 的 Datetime 规则,也就是说当遇到一些 Python 特定的高级数据类型的时候,Json 会因为没有标准而无法进行序列化,而接下来介绍的这个工具会解决这个问题。

Pickle 序列化

Pickle 和 Json 不同的是,Pickle 是 Python 专属的序列化方案,可以转化大多数 Python 的数据类型,并且储存方式是二进制(Byte Code)。二进制的储存方式只有机器才能理解,但是同时也保证了一定的数据隐秘性和高效性。

下面我们来看如何用 Pickle 来实现数据序列化:

In [1]:import pickle
In [2]:with open('abc.pk', 'wb') as file_to_write:
           pickle.dump(abc_dict, file_to_write)
In [3]:with open('abc.pk', 'rb') as file_to_read:
           abc_dict_pk = pickle.load(file_to_read)
           print(type(abc_dict_pk))
Out [3]:<class 'dict'>
  1. 调用 Pickle 模块。
  2. 这里打开文件的方式是 'wb', 因为 pickle 写入的是二进制格式,如果不加上 'b' 的话会导致无法写入文件。
  3. 写入文件之后,再用 pickle 读出数据,同样的因为读取的是二进制,我们用了 'rb' 模式。然后我们检查返回的数据是否是字典类。

我们会发现 Pickle 的语法和 Json 非常相似,虽然本身两者对数据序列化的处理方式皆然不同,但是得益于 Python 的高级接口抽象 (Interface Abstraction),记得 鸭子类型:

我们并不关心对象是什么类型,到底是不是鸭子,只关心行为。

这里两个方法的行为都是在序列化数据,所以在调用方程上感觉完全一样。但是本质上 Json 写入文件的是字符串,而 Pickle 则是把数据转化成了二进制,两个是完全不同的处理方案。


小结

现在流行的数据序列化方案还有 Protobuf, 一个谷歌开发的快速轻量级方案:

protocolbuffers/protobuf​github.com
7fb77a6bdf17d21d3b43697f23454e09.png

另一个是结合了Json 和 二进制优势的 Bson:

BSON (Binary JSON) Serialization​bsonspec.org

在一个大数据任务当中,通常需要多任务并行和串行结合运算加快速度。为了防止中间一环失败而导致整个任务重启,往往会在中间步骤把数据保存下来,就像下图:

bb063a044d4173b6047d1af8b4493f05.png
Map Reduce 利用 Transient Data (临时数据) 来做进度保存

在之后的课程中,Json 和 Pickle 都会频繁的用到的领域有:

  • 大数据处理,消费者数据流。
  • 高并发的科学计算。
  • 建立一个神经网络。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值