我有很多已知架构的python dicts。例如,模式定义为pyspark StructType,如下所示:
from pyspark.sql.types import *
dict_schema = StructType([
StructField("upload_time", TimestampType(), True),
StructField("name", StringType(), True),
StructField("value", StringType(), True),
])
我想有效地将每个dict对象序列化为字节数组。什么序列化方法会给我最小的有效载荷?我不想使用pickle,因为有效负载非常大(它将模式嵌入到每个序列化对象中)。
谢谢,
答案 0 :(得分:0)
您可以使用内置的struct
模块。只需“打包”值:
import struct
struct.pack('Q10s5s`, time, name, value)
假设时间是64位int,名称最多10个字符,值最多20个字符。你需要调整它。如果名称和值的长度不一致(您不希望在填充上浪费空间),您可能还会考虑将字符串存储为以空字符结尾的字节序列。
另一个好方法是使用NumPy,假设字符串具有相当一致的长度:
import numpy as np
a = np.empty(1000, [('time', 'u8'), ('name', 'S10'), ('value', 'S20')])
np.save(filename, a)
这将在文件顶部包含各种“模式”;如果你真的想要,你可以编写没有该模式的原始数组。
答案 1 :(得分:0)
我使用msgpack
(https://msgpack.org/)并根据排序的键对字典值进行排序。我使用zip
用打包的值重建密钥。
据我所知,msgpack的大小性能通常与struct
相当。
就CPU性能而言,msgpack的编码速度要慢10倍,解码速度要慢50%。 msgpack本身可以处理多种格式,并且可以使用JSON之类的编码/解码钩子进行扩展,从而使事情变得更加容易。
在速度方面,...
import time
import msgpack
import struct
_time = int(time.time())
_keys = ('time', 'name', 'value')
_values = (_time, 'name', 'value')
as_msgpack = msgpack.packb(_values, use_bin_type=True)
as_struct = struct.pack('Q10s5s', _time, 'name', 'value')
def test_so_msgpack_encode():
as_msgpack = msgpack.packb(_values, use_bin_type=True)
return as_msgpack
def test_so_struct_encode():
as_struct = struct.pack('Q10s5s', _time, 'name', 'value')
return as_struct
def test_so_msgpack_decode():
_decoded = msgpack.unpackb(as_msgpack)
return dict(zip(_keys, _decoded))
def test_so_struct_decode():
_decoded = struct.unpack('Q10s5s', as_struct)
return dict(zip(_keys, _decoded))
print(timeit.timeit("test_so_msgpack_encode()", setup="from __main__ import test_so_msgpack_encode", number=10000))
print(timeit.timeit("test_so_struct_encode()", setup="from __main__ import test_so_struct_encode", number=10000))
print(timeit.timeit("test_so_msgpack_decode()", setup="from __main__ import test_so_msgpack_decode", number=10000))
print(timeit.timeit("test_so_struct_decode()", setup="from __main__ import test_so_struct_decode", number=10000))
就速度而言,虽然有10倍的因素……但这不太可能成为问题。我在具有10年历史(2008年)的计算机上运行了以上示例,以说明10000次以上的迭代:
编码:
0.0745489597321 # msgpack
0.00702214241028 # struct
解码:
0.0458550453186 # msgpack
0.0313770771027 # struct
因此可以通过struct使其运行更快,但是IMHO msgpack提供了更多功能。
注意:以上并非完全相等的检验;我使用了上面的struct unpack结构,似乎将值填充了几个字节。可以固定在包装中或拆开包装,并会影响结果。