Python 2.7:使用"lzma"模块压缩XZ格式数据
我正在尝试使用Python 2.7.6中的lzma模块,想看看能否创建XZ格式的压缩文件,以便在未来的项目中使用。我的实验代码如下:
import lzma as xz
in_file = open('/home/ki2ne/Desktop/song.wav', 'rb')
input_data = in_file.read()
compressed_data = xz.compress(input_data)
out_file = open('/home/ki2ne/Desktop/song.wav.xz', 'wb')
in_file.close()
out_file.close()
我注意到,生成的文件与我使用普通的xz时,得到了两个不同的校验和(MD5和SHA256),不过我用这两种方法解压缩都没问题——解压后的文件校验和是一样的。这样会有问题吗?
更新:我找到了解决办法,通过peterjc的Git仓库安装了一个回溯版本(来自Python 3.3),现在显示的校验和是一样的。不确定这是否有帮助,但我确保我的库中没有安装LZMA Python模块,以避免可能的名称冲突。
这是我用来确认的测试代码:
# I have created two identical text files with some random phrases
from subprocess import call
from hashlib import sha256
from backports import lzma as xz
f2 = open("test2.txt" , 'rb')
f2_buf = buffer(f2.read())
call(["xz", "test1.txt"])
f2_xzbuf = buffer(xz.compress(f2_buf))
f1 = open("test1.txt.xz", 'rb')
f1_xzbuf = buffer(f1.read())
f1.close(); f2.close()
f1sum = sha256(); f2sum = sha256()
f1sum.update(f1_xzbuf); f2sum.update(f2_xzbuf)
if f1sum.hexdigest() == f2sum.hexdigest():
print "Checksums OK"
else:
print "Checksum Error"
我也用常规的sha256sum进行了验证(当我把数据写入文件时)。
2 个回答
在我的情况下(Ubuntu/Mint),为了在 Python 2.7 中使用 lzma
模块,我直接用 pip
安装了 backports.lzma
(我没有使用 github),需要用 sudo
或者以 root 用户身份来操作:
pip2 install backports.lzma
顺便说一下,pip2
有一个 --user
选项,这个选项不需要超级用户权限,只会为本地用户安装模块,但我没有测试过这个方法。
在执行 pip
安装之前,你还需要通过你的包管理器安装一个必需的依赖:库 liblzma
。
在我的情况下,包的名称是 liblzma5
和 liblzma-dev
,但不同的 Linux 发行版/版本可能包的名称会有所不同。
补充一下:我在另一个 Linux 环境(未知的集群发行版)上也成功重复了同样的操作,使用的是 conda
:
conda install backports
conda install backports.lzma --name pyEnvName
希望对你有帮助
我觉得压缩文件之间的差异不需要太担心。因为根据压缩格式和在.xz
文件中使用的校验和类型,压缩后的数据可能会有所不同,但这并不影响文件的实际内容。
补充说明 我进一步研究了这个问题,并写了一个脚本来测试Python2.x的PyLZMA模块和Python3.x内置的lzma模块。
from __future__ import print_function
try:
import lzma as xz
except ImportError:
import pylzma as xz
import os
# compress with xz command line util
os.system('xz -zkf test.txt')
# now compress with lib
with open('test.txt', 'rb') as f, open('test.txt.xzpy', 'wb') as out:
out.write(xz.compress(bytes(f.read())))
# compare the two files
from hashlib import md5
with open('test.txt.xz', 'rb') as f1, open('test.txt.xzpy', 'rb') as f2:
hash1 = md5(f1.read()).hexdigest()
hash2 = md5(f2.read()).hexdigest()
print(hash1, hash2)
assert hash1 == hash2
这个脚本用xz
命令行工具和Python模块来压缩一个文件test.txt
,然后比较结果。在Python3中,lzma模块的结果和xz
是一样的,但在Python2中,PyLZMA模块的结果却不同,无法用xz命令行工具解压。
你在Python2中使用的那个叫“lzma”的模块是什么?你用什么命令来压缩数据的呢?
补充说明 2 好吧,我找到了Python2的pyliblzma模块。不过它似乎默认使用CRC32作为校验和算法(其他的使用CRC64),而且有一个bug导致无法更改校验和算法,具体可以查看这个链接 https://bugs.launchpad.net/pyliblzma/+bug/1243344
你可以尝试用xz -C crc32
来压缩文件,看看结果是否有变化,但我还是没能成功用Python2的库生成一个有效的压缩文件。