lzma
--- 使用 LZMA 演算法進行壓縮¶
在 3.3 版本加入。
原始碼: Lib/lzma.py
此模組提供類和便捷函式,用於使用 LZMA 壓縮演算法壓縮和解壓縮資料。還包括一個檔案介面,支援 xz 實用工具所使用的 .xz
和舊式 .lzma
檔案格式,以及原始壓縮流。
此模組提供的介面與 bz2
模組的介面非常相似。請注意 LZMAFile
和 bz2.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 引數可以是一個實際的檔名(以
str
、bytes
或類路徑物件的形式給出),在這種情況下,將開啟指定的檔案;或者它也可以是一個已存在的檔案物件,用於讀取或寫入。mode 引數可以是二進位制模式的
"r"
,"rb"
,"w"
,"wb"
,"x"
,"xb"
,"a"
或"ab"
中的任意一個,或文字模式的"rt"
,"wt"
,"xt"
, 或"at"
。預設值為"rb"
。當開啟檔案用於讀取時,format 和 filters 引數的含義與
LZMADecompressor
的相同。在這種情況下,不應使用 check 和 preset 引數。當開啟檔案用於寫入時,format、check、preset 和 filters 引數的含義與
LZMACompressor
的相同。對於二進位制模式,此函式等效於
LZMAFile
建構函式:LZMAFile(filename, mode, ...)
。在這種情況下,不得提供 encoding、errors 和 newline 引數。對於文字模式,會建立一個
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 引數指定要包裝的檔案物件,或要開啟的檔案的名稱(作為str
、bytes
或類路徑物件)。當包裝一個已存在的檔案物件時,該被包裝的檔案在LZMAFile
關閉時將不會被關閉。mode 引數可以是
"r"
用於讀取(預設),"w"
用於覆蓋寫入,"x"
用於獨佔建立,或"a"
用於追加。這些也可以分別等效地寫為"rb"
、"wb"
、"xb"
和"ab"
。如果 filename 是一個檔案物件(而不是一個實際的檔名),模式
"w"
不會截斷檔案,而是等同於"a"
。當開啟檔案進行讀取時,輸入檔案可以是多個獨立壓縮流的串聯。這些流會被透明地解碼為單個邏輯流。
當開啟檔案用於讀取時,format 和 filters 引數的含義與
LZMADecompressor
的相同。在這種情況下,不應使用 check 和 preset 引數。當開啟檔案用於寫入時,format、check、preset 和 filters 引數的含義與
LZMACompressor
的相同。LZMAFile
支援io.BufferedIOBase
指定的所有成員,除了detach()
和truncate()
。支援迭代和with
語句。還提供以下方法和屬性
- peek(size=-1)¶
返回緩衝的資料,而不移動檔案位置。除非已到達檔案末尾(EOF),否則將至少返回一個位元組的資料。返回的確切位元組數是未指定的(size 引數被忽略)。
- mode¶
讀取時為
'rb'
,寫入時為'wb'
。在 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_ALONE
和FORMAT_RAW
的預設值(也是唯一可接受的值)。CHECK_CRC32
:32 位迴圈冗餘校驗。CHECK_CRC64
:64 位迴圈冗餘校驗。這是FORMAT_XZ
的預設值。CHECK_SHA256
:256 位安全雜湊演算法。
如果指定的檢查不受支援,則會引發
LZMAError
。壓縮設定可以指定為預設壓縮級別(使用 preset 引數),也可以詳細指定為自定義過濾器鏈(使用 filters 引數)。
preset 引數(如果提供)應該是一個介於
0
和9
(含)之間的整數,可選地與常量PRESET_EXTREME
進行“或”運算。如果既未提供 preset 也未提供 filters,則預設行為是使用PRESET_DEFAULT
(預設級別6
)。更高的預設會產生更小的輸出,但會使壓縮過程變慢。備註
除了更耗費 CPU 之外,使用更高預設進行壓縮還需要更多的記憶體(並且產生的輸出需要更多記憶體來解壓縮)。例如,使用預設
9
時,一個LZMACompressor
物件的開銷可能高達 800 MiB。因此,通常最好堅持使用預設預設。filters 引數(如果提供)應該是一個過濾器鏈說明符。詳情請參見指定自定義過濾器鏈。
- compress(data)¶
壓縮 data(一個
bytes
物件),返回一個包含至少部分輸入資料的壓縮資料的bytes
物件。部分 data 可能會被內部緩衝,以供後續呼叫compress()
和flush()
時使用。返回的資料應與之前任何compress()
呼叫的輸出拼接在一起。
- class lzma.LZMADecompressor(format=FORMAT_AUTO, memlimit=None, filters=None)¶
建立一個解壓器物件,可用於增量解壓資料。
若要更方便地一次性解壓縮整個壓縮流,請參閱
decompress()
。format 引數指定應使用的容器格式。預設值為
FORMAT_AUTO
,可以解壓縮.xz
和.lzma
檔案。其他可能的值是FORMAT_XZ
、FORMAT_ALONE
和FORMAT_RAW
。memlimit 引數指定解壓器可以使用的記憶體量限制(以位元組為單位)。使用此引數時,如果無法在給定的記憶體限制內解壓縮輸入,解壓縮將失敗並引發
LZMAError
。filters 引數指定用於建立被解壓縮流的過濾器鏈。如果 format 是
FORMAT_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
物件。有關 format、check、preset 和 filters 引數的說明,請參閱上面的
LZMACompressor
。
- lzma.decompress(data, format=FORMAT_AUTO, memlimit=None, filters=None)¶
解壓縮 data(一個
bytes
物件),返回未壓縮的資料作為一個bytes
物件。如果 data 是多個不同壓縮流的串聯,則解壓縮所有這些流,並返回結果的串聯。
有關 format、memlimit 和 filters 引數的說明,請參閱上面的
LZMADecompressor
。
雜項¶
- lzma.is_check_supported(check)¶
如果給定的完整性檢查在此係統上受支援,則返回
True
。CHECK_NONE
和CHECK_CRC32
總是受支援的。CHECK_CRC64
和CHECK_SHA256
可能不可用,如果你使用的是使用有限功能集編譯的 liblzma 版本。
指定自定義過濾器鏈¶
過濾器鏈說明符是一個字典序列,其中每個字典包含單個過濾器的 ID 和選項。每個字典必須包含鍵 "id"
,並且可能包含其他鍵以指定過濾器相關的選項。有效的過濾器 ID 如下:
壓縮過濾器
FILTER_LZMA1
(用於FORMAT_ALONE
)FILTER_LZMA2
(用於FORMAT_XZ
和FORMAT_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。mode
:MODE_FAST
或MODE_NORMAL
。nice_len
:匹配的“適宜長度”應為何值。應為 273 或更小。mf
:使用何種匹配查詢器 –MF_HC3
、MF_HC4
、MF_BT2
、MF_BT3
或MF_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")