【问题标题】:Python 2.7: Compressing data with the XZ format using the "lzma" modulePython 2.7:使用“lzma”模块以 XZ 格式压缩数据
【发布时间】:2014-03-13 05:47:13
【问题描述】:

我正在尝试使用 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 存储库 (link here) 安装反向端口(来自 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 验证了它(当我将数据写入文件时)。

【问题讨论】:

  • 我希望你在某个时候写信给out_file
  • 糟糕 - 我在示例中省略了这个 - 但是是的,我确实在实际脚本中写出了文件。

标签: python checksum lzma xz


【解决方案1】:

我不会担心压缩文件的差异 - 根据容器格式和 .xz 文件中使用的校验和类型,压缩数据可能会有所不同,但不会影响内容。

编辑我一直在进一步研究,并编写了这个脚本来测试 PyLZMA Python2.x 模块和 lzma Python3.x 内置模块

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”,您使用什么命令来压缩数据?

EDIT 2 好的,我找到了 Python2 的 pyliblzma 模块。然而,它似乎使用 CRC32 作为默认校验和算法(其他人使用 CRC64)并且有一个错误阻止更改校验和算法https://bugs.launchpad.net/pyliblzma/+bug/1243344

您可以尝试使用xz -C crc32 进行压缩以比较结果,但我仍然没有成功使用 Python2 库制作有效的压缩文件。

【讨论】:

  • 感谢您的澄清。我正想知道,如果我用 Python 制作 .tar.xz 档案并分发它们,有人可能会指出它并担心它会被篡改。
  • 我将发行版中的python-lzma 包用于我在脚本中使用的模块。我已经使用示例中的脚本和使用xz-utils 包中的xz 命令(使用脚本外部的终端会话)测试了压缩数据。我使用md5sumsha256sum 对这两种方法的文件进行了校验和。
【解决方案2】:

在我的情况下(Ubuntu/Mint),为了在 Pyhton 2.7 中使用 lzma 模块,我直接安装了 backports.lzmapip (我没有使用 github),使用 sudoroot 用户:

pip2 install backports.lzma

FYI pip2--user 选项,不需要超级用户权限并且仅为本地用户安装模块,但我没有对此进行测试。

除了执行pip 安装之外,您还必须使用包管理器安装一个强制依赖项:库liblzma

在我的例子中,包名是liblzma5liblzma-dev,但包名可能在 Linux 发行版/发行版之间有所不同。

P.s:我还在不同的 Linux 环境(未知集群发行版)上使用 conda 成功重复了相同的操作:

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

希望有用

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多