简而言之:在Python中可用的各种压缩算法,包括gzip
、bz2
和lzma
等,哪一个具有最佳的解压缩性能?
完整讨论:
Python 3中有各种模块可用于压缩/解压缩数据
,包括gzip
、bz2
和lzma
。此外,gzip
和bz2
还有不同的压缩级别可供设置。
如果我要平衡文件大小(/压缩比)和解压缩速度(不关心压缩速度),哪个选择会是最好的?解压缩速度比文件大小更重要,但因为所涉及到的未压缩文件每个约为600-800MB(32位RGB .png图像文件),而且我有十几个这样的文件,所以我确实需要一些压缩。
我的使用案例是从磁盘加载十几张图片,对它们进行一些处理(作为numpy数组),然后在程序中使用处理后的数组数据。这些图片永远不会改变,我每次运行程序时只需要加载它们。处理时间与加载时间大约相同(几秒钟),因此我正在尝试通过保存处理后的数据(使用pickle)而不是每次加载原始未经处理的图像来节省一些加载时间。最初的测试结果很有希望——加载原始/未压缩的pickled数据只需不到一秒钟,而加载和处理原始图像需要3或4秒钟——但文件大小约为600-800MB,而原始png图像仅约5MB。因此,我希望能够在加载时间和文件大小之间取得平衡,通过以压缩格式存储选定数据来实现。更新:实际上,情况比我上面描述的要复杂一些。我的应用程序使用PySide2,因此我可以访问Qt库。如果我使用pillow(PIL.Image)读取图像并将其转换为numpy数组,则实际上不需要进行任何处理,但将图像读入数组的总时间约为4秒。如果我改为使用QImage读取图像,则必须对结果进行一些处理,以使其可用于我的程序的其余部分,由于QImage加载数据的字节顺序问题,基本上我必须交换位顺序,然后旋转每个“像素”,使α通道(显然由QImage添加)最后而不是最前。整个过程大约需要3.8秒,因此比仅使用PIL略快。如果我以未压缩的方式保存numpy数组,则可以在0.8秒内重新加载它们,因此速度最快,但文件大小较大。
┌────────────┬────────────────────────┬───────────────┬─────────────┐
│ Python Ver │ Library/Method │ Read/unpack + │ Compression │
│ │ │ Decompress (s)│ Ratio │
├────────────┼────────────────────────┼───────────────┼─────────────┤
│ 3.7.2 │ pillow (PIL.Image) │ 4.0 │ ~0.006 │
│ 3.7.2 │ Qt (QImage) │ 3.8 │ ~0.006 │
│ 3.7.2 │ numpy (uncompressed) │ 0.8 │ 1.0 │
│ 3.7.2 │ gzip (compresslevel=9) │ ? │ ? │
│ 3.7.2 │ gzip (compresslevel=?) │ ? │ ? │
│ 3.7.2 │ bz2 (compresslevel=9) │ ? │ ? │
│ 3.7.2 │ bz2 (compresslevel=?) │ ? │ ? │
│ 3.7.2 │ lzma │ ? │ ? │
├────────────┼────────────────────────┼───────────────┼─────────────┤
│ 3.7.3 │ ? │ ? │ ? │
├────────────┼────────────────────────┼───────────────┼─────────────┤
│ 3.8beta1 │ ? │ ? │ ? │
├────────────┼────────────────────────┼───────────────┼─────────────┤
│ 3.8.0final │ ? │ ? │ ? │
├────────────┼────────────────────────┼───────────────┼─────────────┤
│ 3.5.7 │ ? │ ? │ ? │
├────────────┼────────────────────────┼───────────────┼─────────────┤
│ 3.6.10 │ ? │ ? │ ? │
└────────────┴────────────────────────┴───────────────┴─────────────┘
示例.png图像: 以这个大小为5.0Mb的png图像,是阿拉斯加海岸线的相当高分辨率图像为例。
用于png/PIL情况的代码(加载到numpy
数组中):
from PIL import Image
import time
import numpy
start = time.time()
FILE = '/path/to/file/AlaskaCoast.png'
Image.MAX_IMAGE_PIXELS = None
img = Image.open(FILE)
arr = numpy.array(img)
print("Loaded in", time.time()-start)
这个加载过程在我的Python 3.7.2机器上大约需要4.2秒。
或者,我可以加载由上面创建的数组生成的未压缩pickle文件。
未压缩pickle加载案例的代码:
import pickle
import time
start = time.time()
with open('/tmp/test_file.pickle','rb') as picklefile:
arr = pickle.load(picklefile)
print("Loaded in", time.time()-start)
在我的机器上,从这个未压缩的pickle文件加载需要大约0.8秒。