lzma — 使用 LZMA 算法压缩

3.3 版新增。

**源代码:** Lib/lzma.py


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

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

异常 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 版更改: 接受 类路径对象

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* 传递一个文件对象来构造的)。

在 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 进行 OR 运算。如果既没有给出 *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 始终受支持。 如果您使用的是使用有限功能集编译的 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_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")