lzma --- 使用 LZMA 算法进行压缩

在 3.3 版本加入。

源代码: Lib/lzma.py


此模块提供类和便捷函数,用于使用 LZMA 压缩算法压缩和解压缩数据。还包括一个文件接口,支持 xz 实用工具所使用的 .xz 和旧式 .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 版本发生变更: 接受 path-like object

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 的文件位置,但它可能会改变底层文件对象的位置(例如,如果 LZMAFile 是通过为 filename 传递一个文件对象来构造的)。

mode

读取时为 'rb',写入时为 'wb'

在 3.13 版本加入。

name

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

在 3.13 版本加入。

在 3.4 版本发生变更: 添加了对 "x""xb" 模式的支持。

在 3.5 版本发生变更: read() 方法现在接受 None 作为参数。

在 3.6 版本发生变更: 接受 path-like object

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

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

备注

除了更耗费 CPU 之外,使用更高预设进行压缩还需要更多的内存(并且产生的输出需要更多内存来解压缩)。例如,使用预设 9 时,一个 LZMACompressor 对象的开销可能高达 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() 的调用可以提供 datab'' 以获取更多输出。

如果所有输入数据都已解压缩并返回(或者是因为数据小于 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 总是受支持的。CHECK_CRC64CHECK_SHA256 可能不可用,如果你使用的是使用有限功能集编译的 liblzma 版本。

指定自定义过滤器链

过滤器链说明符是一个字典序列,其中每个字典包含单个过滤器的 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_HC3MF_HC4MF_BT2MF_BT3MF_BT4

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

增量过滤器存储字节之间的差异,在某些情况下为压缩器产生更具重复性的输入。它支持一个选项 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")