Skip to main content

13.4. lzma —使用LZMA算法进行压缩

3.3 新版功能.

源代码: Lib/lzma.py


此模块提供了使用LZMA压缩算法压缩和解压缩数据的类和便利功能。还包括支持 xz 实用程序使用的 .xz 和传统 .lzma 文件格式的文件接口,以及原始压缩流。

该模块提供的接口与 bz2 模块非常相似。但是,请注意,LZMAFilenot 线程安全的,与 bz2.BZ2File 不同,因此,如果您需要使用来自多个线程的单个 LZMAFile 实例,则需要使用锁来保护它。

exception lzma.LZMAError

当在压缩或解压缩期间或在初始化压缩器/解压缩器状态期间发生错误时引发此异常。

13.4.1. 读取和写入压缩文件

lzma.open(filename, mode="rb", *, format=None, check=-1, preset=None, filters=None, encoding=None, errors=None, newline=None)

以二进制或文本模式打开LZMA压缩文件,返回 file object

filename 参数可以是实际的文件名(作为 strbytespath-like object 对象给出),在这种情况下,命名文件被打开,或者它可以是要读取或写入的现有文件对象。

mode 参数可以是用于二进制模式的 "r""rb""w""wb""x""xb""a""ab" 中的任何一个,或者对于文本模式是 "rt""wt""xt""at" 中的任何一个。默认值为 "rb"

当打开文件进行读取时,formatfilters 参数具有与 LZMADecompressor 相同的含义。在这种情况下,不应使用 checkpreset 参数。

当打开要写入的文件时,formatcheckpresetfilters 参数具有与 LZMACompressor 相同的含义。

对于二进制模式,此函数等同于 LZMAFile 构造函数:LZMAFile(filename, mode, ...)。在这种情况下,不能提供 encodingerrorsnewline 参数。

对于文本模式,将创建 LZMAFile 对象,并将其包装在具有指定编码,错误处理行为和行结尾的 io.TextIOWrapper 实例中。

在 3.4 版更改: 增加了对 "x""xb""xt" 模式的支持。

在 3.6 版更改: 接受 path-like object

class lzma.LZMAFile(filename=None, mode="r", *, format=None, check=-1, preset=None, filters=None)

以二进制模式打开LZMA压缩文件。

LZMAFile 可以包装已打开的 file object,或直接在命名文件上操作。 filename 参数指定要打包的文件对象,或要打开的文件的名称(作为 strbytespath-like object 对象)。当包装现有文件对象时,包装的文件将不会在关闭 LZMAFile 时关闭。

mode 参数可以是用于读取的 "r" (默认),用于覆盖的 "w",用于独占创建的 "x" 或用于附加的 "a"。这些可以分别等效地给出为 "rb""wb""xb""ab"

如果 filename 是文件对象(而不是实际文件名),"w" 的模式不截断该文件,而是等效于 "a"

当打开用于读取的文件时,输入文件可以是多个单独的压缩流的级联。这些被透明地解码为单个逻辑流。

当打开文件进行读取时,formatfilters 参数具有与 LZMADecompressor 相同的含义。在这种情况下,不应使用 checkpreset 参数。

当打开要写入的文件时,formatcheckpresetfilters 参数具有与 LZMACompressor 相同的含义。

LZMAFile 支持由 io.BufferedIOBase 指定的所有成员,除了 detach()truncate()。支持迭代和 with 语句。

还提供以下方法:

peek(size=-1)

返回缓冲数据,而不提前文件位置。将返回至少一个字节的数据,除非已经到达EOF。返回的确切字节数未指定(忽略 size 参数)。

注解

当调用 peek() 不改变 LZMAFile 的文件位置时,它可以改变底层文件对象的位置(例如,如果通过传递 filename 的文件对象来构造 LZMAFile)。

在 3.4 版更改: 增加了对 "x""xb" 模式的支持。

在 3.5 版更改: read() 方法现在接受 None 的参数。

在 3.6 版更改: 接受 path-like object

13.4.2. 压缩和解压缩内存中的数据

class lzma.LZMACompressor(format=FORMAT_XZ, check=-1, preset=None, filters=None)

创建压缩器对象,可用于逐步压缩数据。

有关压缩单个数据块的更方便的方法,请参阅 compress()

format 参数指定应使用哪种容器格式。可能的值为:

  • FORMAT_XZ.xz 容器格式。

    这是默认格式。

  • FORMAT_ALONE:旧版 .lzma 容器格式。

    此格式比 .xz 更受限制 - 它不支持完整性检查或多个过滤器。

  • FORMAT_RAW:原始数据流,不使用任何容器格式。

    此格式说明符不支持完整性检查,并要求您始终指定自定义过滤器链(用于压缩和解压缩)。此外,以这种方式压缩的数据不能使用 FORMAT_AUTO 解压缩(参见 LZMADecompressor)。

check 参数指定要包括在压缩数据中的完整性检查的类型。此检查用于解压缩时,以确保数据未被损坏。可能的值为:

  • CHECK_NONE:无完整性检查。这是 FORMAT_ALONEFORMAT_RAW 的默认(和唯一可接受的值)。

  • CHECK_CRC32:32位循环冗余校验。

  • CHECK_CRC64:64位循环冗余校验。这是 FORMAT_XZ 的默认值。

  • CHECK_SHA256:256位安全散列算法。

如果不支持指定的检查,则会引发 LZMAError

压缩设置可以指定为预设压缩级别(使用 preset 参数),也可以详细指定为自定义过滤器链(使用 filters 参数)。

preset 参数(如果提供)应该是 09 (包括)之间的整数,可选地与常量 PRESET_EXTREME 进行OR运算。如果既没有给出 preset 也没有给出 filters,则默认行为是使用 PRESET_DEFAULT (预设电平 6)。较高的预设产生较小的输出,但使压缩过程较慢。

注解

除了更多的CPU密集,具有更高预设的压缩还需要更多的内存(并产生需要更多内存来解压缩的输出)。例如,使用预设的 9LZMACompressor 对象的开销可以高达800 MiB。因此,通常最好坚持使用默认预设。

filters 参数(如果提供)应为过滤器链说明符。有关详细信息,请参阅 指定自定义过滤器链

compress(data)

压缩 databytes 对象),返回包含至少部分输入的压缩数据的 bytes 对象。一些 data 可以在内部缓冲,以用于稍后对 compress()flush() 的调用。返回的数据应该与任何先前对 compress() 的调用的输出连接。

flush()

完成压缩过程,返回包含存储在压缩器内部缓冲区中的任何数据的 bytes 对象。

在调用此方法后,无法使用压缩器。

class lzma.LZMADecompressor(format=FORMAT_AUTO, memlimit=None, filters=None)

创建解压缩器对象,可用于逐步解压缩数据。

为了更方便地一次解压缩整个压缩流,请参阅 decompress()

format 参数指定应使用的容器格式。默认值为 FORMAT_AUTO,它可以解压缩 .xz.lzma 文件。其他可能的值是 FORMAT_XZFORMAT_ALONEFORMAT_RAW

memlimit 参数指定解压缩程序可以使用的内存量的限制(以字节为单位)。当使用此参数时,如果无法在给定的内存限制内解压缩输入,则使用 LZMAError 解压缩将失败。

filters 参数指定用于创建解压缩流的过滤器链。如果 formatFORMAT_RAW,则此参数是必需的,但不应用于其他格式。有关过滤器链的更多信息,请参见 指定自定义过滤器链

注解

这个类不透明地处理包含多个压缩流的输入,与 decompress()LZMAFile 不同。要使用 LZMADecompressor 解压缩多流输入,必须为每个流创建一个新的解压缩器。

decompress(data, max_length=-1)

解压缩 databytes-like object),以字节形式返回未压缩数据。一些 data 可以在内部缓冲,以用于稍后对 decompress() 的调用。返回的数据应该与任何以前对 decompress() 的调用的输出连接。

如果 max_length 是非负的,则返回解压缩数据的大多数 max_length 字节。如果达到此限制并且可以产生进一步的输出,则 needs_input 属性将被设置为 False。在这种情况下,对 decompress() 的下一次调用可以提供 data 作为 b'' 以获得更多的输出。

如果所有输入数据被解压缩和返回(由于这小于 max_length 字节,或者因为 max_length 为负),则 needs_input 属性将被设置为 True

在流到达结束后尝试解压缩数据会引发 EOFError。在流结束后找到的任何数据将被忽略并保存在 unused_data 属性中。

在 3.5 版更改: 添加了 max_length 参数。

check

输入流使用的完整性检查的ID。这可以是 CHECK_UNKNOWN,直到足够的输入已经被解码以确定它使用什么完整性检查。

eof

True,如果已经到达流末尾标记。

unused_data

压缩流结束后找到的数据。

在达到流的结束之前,这将是 b""

needs_input

False,如果 decompress() 方法可以在需要新的未压缩输入之前提供更多的解压缩数据。

3.5 新版功能.

lzma.compress(data, format=FORMAT_XZ, check=-1, preset=None, filters=None)

压缩 databytes 对象),将压缩数据作为 bytes 对象返回。

有关 formatcheckpresetfilters 参数的说明,请参阅上面的 LZMACompressor

lzma.decompress(data, format=FORMAT_AUTO, memlimit=None, filters=None)

解压缩 databytes 对象),将未压缩数据作为 bytes 对象返回。

如果 data 是多个不同压缩流的级联,则解压缩所有这些流,并返回结果的级联。

有关 formatmemlimitfilters 参数的描述,请参阅上面的 LZMADecompressor

13.4.3. 杂

lzma.is_check_supported(check)

如果在此系统上支持给定的完整性检查,则返回true。

始终支持 CHECK_NONECHECK_CRC32。如果您使用的是使用有限功能集编译的 liblzma 版本,CHECK_CRC64CHECK_SHA256 可能无法使用。

13.4.4. 指定自定义过滤器链

过滤器链说明符是字典序列,其中每个字典包含单个过滤器的ID和选项。每个字典必须包含密钥 "id",并且可以包含用于指定过滤器相关选项的附加键。有效的过滤器ID如下:

  • 压缩过滤器:
    • FILTER_LZMA1 (用于 FORMAT_ALONE

    • FILTER_LZMA2 (用于 FORMAT_XZFORMAT_RAW

  • Delta滤波器:
    • FILTER_DELTA

  • 分支 - 调用跳转(BCJ)过滤器:
    • FILTER_X86

    • FILTER_IA64

    • FILTER_ARM

    • FILTER_ARMTHUMB

    • FILTER_POWERPC

    • FILTER_SPARC

过滤器链最多可以包含4个过滤器,不能为空。链中的最后一个过滤器必须是压缩过滤器,并且任何其他过滤器必须是delta或BCJ过滤器。

压缩过滤器支持以下选项(在字典中表示过滤器的附加条目):

  • preset:压缩预设,用作未明确指定的选项的默认值来源。

  • dict_size:字典大小(以字节为单位)。这应该在4千兆和1.5千兆(包括)之间。

  • lc:文本上下文位的数目。

  • lp:文字位置位数。总和 lc + lp 必须至多为4。

  • pb:位置位数;必须至多为4。

  • modeMODE_FASTMODE_NORMAL

  • nice_len:什么应该被认为是一个“漂亮的长度”的比赛。这应该是273或更少。

  • mf:使用什么匹配finder - MF_HC3MF_HC4MF_BT2MF_BT3MF_BT4

  • depth:匹配查找器使用的最大搜索深度。 0(默认)表示基于其他过滤器选项自动选择。

增量滤波器存储字节之间的差异,在某些情况下为压缩器产生更多的重复输入。它支持一个选项,dist。这指示要减去的字节之间的距离。默认值为1,即取相邻字节之间的差值。

BCJ过滤器旨在应用于机器代码。它们将代码中的相对分支,调用和跳转转换为使用绝对寻址,目的是增加压缩器可利用的冗余。这些过滤器支持一个选项,start_offset。它指定应映射到输入数据开头的地址。默认值为0。

13.4.5. 例子

读取压缩文件:

import lzma
with lzma.open("file.xz") as f:
    file_content = f.read()

创建压缩文件:

import lzma
data = b"Insert Data Here"
with lzma.open("file.xz", "w") as f:
    f.write(data)

压缩内存中的数据:

import lzma
data_in = b"Insert Data Here"
data_out = lzma.compress(data_in)

增量压缩:

import lzma
lzc = lzma.LZMACompressor()
out1 = lzc.compress(b"Some data\n")
out2 = lzc.compress(b"Another piece of data\n")
out3 = lzc.compress(b"Even more data\n")
out4 = lzc.flush()
# Concatenate all the partial results:
result = b"".join([out1, out2, out3, out4])

将压缩数据写入已打开的文件:

import lzma
with open("file.xz", "wb") as f:
    f.write(b"This data will not be compressed\n")
    with lzma.open(f, "w") as lzf:
        lzf.write(b"This *will* be compressed\n")
    f.write(b"Not compressed\n")

使用自定义过滤器链创建压缩文件:

import lzma
my_filters = [
    {"id": lzma.FILTER_DELTA, "dist": 5},
    {"id": lzma.FILTER_LZMA2, "preset": 7 | lzma.PRESET_EXTREME},
]
with lzma.open("file.xz", "w", filters=my_filters) as f:
    f.write(b"blah blah blah")