写点什么

使用 Python 对数据进行压缩

用户头像
★忆先★
关注
发布于: 2021 年 06 月 17 日

之前在工作中遇到一个需求,需要在手机小程序端获取到微信小商店店铺的所有商品数据。由于当时我们没有在后台维护用户的商品数据,选择的解决方案是现场调用商品列表接口,然后缓存在 Redis 里。鉴于 Redis 的内存还是比较宝贵的,而用户的商品数据(转化为 json 格式后)又是一些比较有规律的文本数据,比较适合进行数据压缩,于是我调研了一下 Python 中的数据压缩的方案。

zip标准库

Python 中有一个标准库zip,常用来处理 zip 格式文件,提供的函数和方法也更适合文件操作。在这个案例中我们的数据是通过 http 接口获取的,额外进行一些文件操作有些麻烦和多余,zip标准库并不适合这个场景。

zlib标准库

zlib是一个常用的压缩、解压库,使用了 deflate 算法。zipunzip工具背后其实用的就是zlib。Python 内置了zlib标准库,提供的接口也很简洁易用(zlib.compresszlib.decompress)。


import zlibraw = b'abc' * 100compressed = zlib.compress(raw)print(f'compress ratio =  {len(compressed)/len(raw):.2}') # compress ratio =  0.05assert zlib.decompress(compressed) == raw
复制代码


zlib可以显著压缩数据规模。当然这个例子比较极端,重复了一百遍'abc',能达到 5%的压缩率。在真实场景下,zlib大概能将原始数据压缩到 40%到 50%的大小。



zlib.compress函数的第二个参数level表示压缩级别,范围从 0 到 9,数值越低表示压缩速度越快但压缩率也越高(0 表示只编码而不进行压缩),默认值是-1,在 Python 中一般会使用级别 6。我们可以对比一下不同级别的速度和压缩率。




可以看到,在压缩《西游记》小说原文的场景中,级别 1 和级别 9 的压缩率从 50%提高到了 44%,但级别 1 的耗时只有级别 9 的 20%。在数据大小敏感的场景下下,1%的压缩率的提高也是很可观的。我遇到的这个场景数据是要存在 Redis 里的,并且每个店铺的数据规模有限,倾向于使用更高的压缩率的方案。

lzma标准库

Python 标准库中的lzma(顾名思义,使用 lzma 算法)同样可以用于数据压缩,并且有着更高的压缩率,提供的接口与zlib也很相似。



使用 lzma 可以达到三分之一的压缩率,比级别最高的zlib压缩率还要高十多个百分点,相对应的,压缩速度和解压速度会慢很多。





在实验中, 使用lzma压缩和解压《西游记》的原文的时间是使用级别 9zlib的四倍多。


考虑到微信小商店每个店铺的商品不会很多,花在压缩上的 CPU 时间并不长,还要考虑到请求商品列表接口的耗时,我最后在这个业务中选用了lzma标准库。

zstd

zliblzma都是 Python 标准库,可以开箱即用。Pypi 上还是有一些其他的数据压缩、解压的库,在这里介绍一下zstd


zstd(Zstandard)是 Facebook 推出的一个压缩算法,提供zlib级别的实时压缩速率和更高的压缩比。标准的zstd实现是官方的 C lib,在 Pypi 上也有同名的 Python 绑定实现。



zstd有 22 个级别,选用压缩率最高的级别压缩效果和lzma不相上下,压缩速度会快上一些(一般情况下不会用这么高的级别,压缩速度会快很多),但解压速度比lzma要快十倍。在我遇到的这个场景下,解压的数据量不会太大,这一点解压速度的提升还不值得引入一个第三方库。当然遇到更合适的场景的话,zstd库还是大有所为的。

总结

作为一个自带电池的语言,了解并活用 Python 标准库还是会很大程度上提高开发效率的。

发布于: 2021 年 06 月 17 日阅读数: 11
用户头像

★忆先★

关注

还未添加个人签名 2018.11.12 加入

Python后端开发

评论

发布
暂无评论
使用 Python 对数据进行压缩