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