Python 2.7:使用"lzma"模块压缩XZ格式数据

6 投票
2 回答
17541 浏览
提问于 2025-04-17 22:04

我正在尝试使用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 个回答

0

在我的情况下(Ubuntu/Mint),为了在 Python 2.7 中使用 lzma 模块,我直接用 pip 安装了 backports.lzma(我没有使用 github),需要用 sudo 或者以 root 用户身份来操作:

pip2 install backports.lzma

顺便说一下pip2 有一个 --user 选项,这个选项不需要超级用户权限,只会为本地用户安装模块,但我没有测试过这个方法。

在执行 pip 安装之前,你还需要通过你的包管理器安装一个必需的依赖:库 liblzma

在我的情况下,包的名称是 liblzma5liblzma-dev,但不同的 Linux 发行版/版本可能包的名称会有所不同。

补充一下:我在另一个 Linux 环境(未知的集群发行版)上也成功重复了同样的操作,使用的是 conda

conda install backports
conda install backports.lzma --name pyEnvName

希望对你有帮助

7

我觉得压缩文件之间的差异不需要太担心。因为根据压缩格式和在.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的库生成一个有效的压缩文件。

撰写回答