zoukankan      html  css  js  c++  java
  • Python的序列化

    序列化

    程序在内存中运行时候,使用了一些复杂的数据结构,这些数据结构并不是线性的,但我们在储存数据或传输数据时,必须将这些数据按照先后顺序进行发送或者储存。这就需要将内存中的复杂的数据结构就行序列化处理。

    当然我们还可以忽略这些数据结构,直接将内存从起始地址到终止地址数据按字节逐一发送或者储存,下次使用这些数据时原封不动的还原到内存中,这些数据将会重现。这种序列化后的内容我们通常称为 `Image`。

    Python序列化工具

    pickle

    `pickle`是Python自己的序列化工具包,可以将Python中的数据进行序列化,保存到文件之中。对于不同数据格式,使用起始标志+ 数据 + 结束标志储存数据,不同的数据类型对应的起始标识和终止标识有所区别, 这使得在数据保存可它原来的数据类型,在下一次还原时,可以按照原数据类型进行还原。

    python序列化工具都提供了重要的方法`dumps` 序列化(复杂结构转字符序列)和 `loads`方法(二进制还原数据结构)

    import pickle
    l = {"l": ["a", 1, {123}, {"f":"g"}]}
    pickle_str = pickle.dumps(l)
    with open("test", "w") as f:
        f.write(pickle_str)

    使用 `dumps`方法将复杂的字典+列表的数据结构转化为字符序列的形式写入文件中

    obj = pickle.loads(pickle_str)
    print(obj)
    # obj 对象将被还原为这个字典
    # {"l": ["a", 1, {123}, {"f":"g"}]}

    当序列化类对象的时候,只会对实例进行序列化,实例化实例字典中的数据,和该实例的类对象信息。在内存中恢复数据时会使用源代码重新创建对象,并使用并使用序列化的数据还原信息。
    优点:

    • 保存了原来的数据类型,可以序列化复杂的Python对象,包括自定义的实例对象
    • Python独有的序列化工具,序列化和反序列化效率高,序列化后长度小

    缺点:

    • 只支持Python语言,且Python2和 Python3的pickle协议不兼容,使用局限。

    json

    json(Javascript object Notation) 是一种使用较为广泛,且较为轻量级的数据交换格式,将支持的数据结构知己转化为字符串文本格式,进行数据的传输。 它支持对JavaScript中的几种基本数据类型进行序列化。大部分编程语言提供了兼容这套序列化标准的库实现,用于将各语言自身的数据结构转化成对应的JavaScript数据类型以完成序列化。python 提供json库实现。

    json 格式支持的JavaScript的几种数据类型(详见json http://www.json.org/json-zh.html)

    Python类型json类型
    True true
    False false
    None null
    str string
    int integer
    float float
    list,tuple array
    dict object
    • Python中的set()类型提供json的序列化支持,序列化时可转未list或者tuple进行序列化。
    • lsittuple类型会转化为json的array类型,反序列化时默认会还原为列表类型
    • 所有的json类型都为字符串格式,包括None,True,False类型转化的结果均为字符串,对应的"null",“ture”,“false”。

    json的使用和pickle的使用类似,提供了两个比较重要的 dumps 和 loads方法进行序列化和反序列化。

    import json
    l = {"l": ["a", 1, [123], {"f":"g"}]}
    # 序列化
    json_str = json.dumps(l)
    print(json_str)
    # b'{"l": ["a", 1, [123], {"f": "g"}]}'
    
    # 反序列化
    obj = json.loads(json_str)
    print(obj)
    # {'l': ['a', 1, [123], {'f': 'g'}]} <class 'dict'>

    json序列化是将所有的数据类型都转为为字符串类型进行储存,上面实例中存int类型的1 和 123,序列化后,通过Python的bytes类型的输出可以看出1123都为字符串类型。并且显示的每一字符都是真实的数据,包括上面的space{ } [ ]都占用一个字节的空间。这种无效的数据占用了大量的空间,浪费磁盘空间和发送数据时的网络资源。并且不支持实例对象的直接实例化。

    messagepack

    对于json 这种全部使用字符串序列化的方式,messagepack对这种方式进行优化,形成了一种类似于一种 类型编码 (长度编码) 数据1,数据2数据形式,储存数据1时可以直接储存为原类型的二进制形式,使用了原来的数据类型,避免了数据类型的转化和使用字符串储存时的空间浪费。反序列化数据时候,根据该数据的类型声明完成对应数据类型的解码即可。

    import msgpack
    l = {"l": ["a", 1, [123], {"f":"g"}]}
    
    # 序列化
    msgpack_str = msgpack.dumps(l)
    print(msgpack_str)
    # b'x81xa1lx94xa1ax01x91{x81xa1fxa1g'
    
    # 反序列化
    obj = msgpack.loads(msgpack_str)
    print(obj, type(obj))
    # 反序列化后的内容内层字符串为bytes类型,可以指定loads编码还原原数据类型
    # {b'l': [b'a', 1, [123], {b'f': b'g'}]} <class 'dict'>
    
    obj = msgpack.loads(msgpack_str, encoding="utf_8")
    print(obj, type(obj))
    # 现在内层的字符结果将会进行解码
    # {'l': ['a', 1, [123], {'f': 'g'}]} <class 'dict'>

    优点:

    • 原数据类型储存,避免了类型转换,对于数值类型更节省空间。
    • 相比于json减少了的无效字符,和类型转化,时间和空间上性能都更加优秀。

    缺点

    • msg 和 json相同,不能序列化Python的实例对象。
    • 只能序列化一些基本数据类型的数据

    比较

    import pickle
    import time
    import json
    import msgpack
    import random
    
    def getkey(n):
        yield from ("".join(random.choices("abcdefghijklmnopqrstuvwxyz", k=4)) for _ in range(n))
    
    value = ["a", "hello",{"b": "world"}]
    
    test_data = dict.fromkeys(getkey(1000), value)
    
    for name, package in zip(["json", "msgpack", "pickle"], [json, msgpack, pickle]):
    
        start = time.time()
        for _ in range(10000):
            res_str = package.dumps(test_data)
        stop = time.time()
        print(f"{name:<8}序列化时间为	", stop-start)
    
        start = time.time()
        for _ in range(10000):
            package.loads(res_str)
        stop = time.time()
        print(f"{name:<8}反序列化时间	", stop-start)
    json    序列化时间为     6.5685741901397705
    json    反序列化时间     4.880975961685181
    msgpack 序列化时间为     3.23630428314209
    msgpack 反序列化时间     3.115692377090454
    pickle  序列化时间为     0.965388298034668
    pickle  反序列化时间     1.2167444229125977

    三种序列化数据的长度比较

    for name, package in zip(["json", "msgpack", "pickle"], [json, msgpack, pickle]):
        res_str = package.dumps(test_data)
        print(f"{name:<8}序列化后长度为	", len(res_str))
    
    # 结果
    # json    序列化后长度为     39920
    # msgpack 序列化后长度为     22957
    # pickle  序列化后长度为     15276
  • 相关阅读:
    最近邻插值
    tp类型自动转换和自动完成
    tp读取器和写入器
    tp模型和数据库操作方法
    tp数据库操作
    tp请求和响应
    tp配置+路由+基本操作
    git的常见操作方法
    php 检查该数组有重复值
    公众号的TOKEN配置PHP代码
  • 原文地址:https://www.cnblogs.com/k5210202/p/13070024.html
Copyright © 2011-2022 走看看