lzma — 使用 LZMA 算法进行压缩

3.3 版本新增。

源代码: Lib/lzma.py


此模块提供了使用 LZMA 压缩算法压缩和解压缩数据的类和便捷函数。还包括一个文件接口,支持 .xzxz 实用程序使用的旧式 .lzma 文件格式,以及原始压缩流。

此模块提供的接口与 bz2 模块的接口非常相似。请注意,LZMAFilebz2.BZ2File 不是线程安全的,因此如果需要从多个线程使用单个 LZMAFile 实例,则必须使用锁对其进行保护。

exception lzma.LZMAError

当压缩或解压缩过程中,或者初始化压缩器/解压缩器状态时发生错误时,会引发此异常。

读取和写入压缩文件

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

以二进制或文本模式打开 LZMA 压缩文件,返回一个文件对象

filename 参数可以是实际文件名(以 strbytes路径型 对象的形式给出),在这种情况下,将打开指定的文件,或者它可以是用于读取或写入的现有文件对象。

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 版本中更改: 接受路径型对象

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

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

LZMAFile 可以包装一个已打开的文件对象,或直接对指定文件进行操作。 filename 参数指定要包装的文件对象或要打开的文件名称(以 strbytes路径型 对象的形式给出)。包装现有文件对象时,当 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)。

mode

'rb' 用于读取,'wb' 用于写入。

3.13 版本新增。

name

lzma 文件名。 等同于底层 文件对象name 属性。

3.13 版本新增。

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

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

在 3.6 版本中更改: 接受路径型对象

在内存中压缩和解压缩数据

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 进行或运算。 如果未给出 presetfilters,则默认行为是使用 PRESET_DEFAULT(预设级别 6)。 较高的预设会产生较小的输出,但会使压缩过程变慢。

注意

除了更加占用 CPU 资源之外,使用较高预设进行压缩还需要更多的内存(并且会产生需要更多内存来解压缩的输出)。 例如,使用预设 9LZMACompressor 对象的开销可能高达 800 MiB。 因此,通常最好坚持使用默认预设。

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

compress(data)

压缩 data(一个 bytes 对象),返回一个 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)

解压缩 data (一个 类字节对象),以字节形式返回解压缩后的数据。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

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

在 3.5 版本中添加。

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

压缩 data (一个 bytes 对象),返回压缩后的数据作为 bytes 对象。

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

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

解压缩 data (一个 bytes 对象),返回解压缩后的数据作为 bytes 对象。

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

有关 formatmemlimitfilters 参数的说明,请参阅上面的 LZMADecompressor

其他

lzma.is_check_supported(check)

如果此系统支持给定的完整性检查,则返回 True

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

指定自定义过滤器链

过滤器链说明符是一系列字典,其中每个字典都包含单个过滤器的 ID 和选项。每个字典必须包含键 "id",并且可以包含其他键来指定与过滤器相关的选项。有效的过滤器 ID 如下

  • 压缩过滤器

    • FILTER_LZMA1 (用于 FORMAT_ALONE)

    • FILTER_LZMA2 (用于 FORMAT_XZFORMAT_RAW)

  • 增量过滤器

    • FILTER_DELTA

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

    • FILTER_X86

    • FILTER_IA64

    • FILTER_ARM

    • FILTER_ARMTHUMB

    • FILTER_POWERPC

    • FILTER_SPARC

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

压缩过滤器支持以下选项(指定为表示过滤器的字典中的其他条目)

  • preset:要用作未显式指定的选项的默认值来源的压缩预设。

  • dict_size:字典大小(以字节为单位)。这应该在 4 KiB 和 1.5 GiB(含)之间。

  • lc:文字上下文位的数量。

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

  • pb:位置位的数量;必须最多为 4。

  • modeMODE_FASTMODE_NORMAL

  • nice_len:对于匹配项,应该认为“合适长度”是什么。这应该为 273 或更少。

  • mf: 使用哪个匹配查找器 – MF_HC3, MF_HC4, MF_BT2, MF_BT3, 或 MF_BT4

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

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

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

示例

读取压缩文件

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")