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