介紹如何使用 Python 的 zipfile 模組,壓縮與解壓縮 ZIP 檔案,並查看 ZIP 檔案資訊。
Python 標準函式庫中的 zipfile 模組可以用來壓縮與解壓縮 ZIP 檔案,以下是使用的教學與範例。
檢查檔案是否為 ZIP 壓縮檔
若要檢查指定的檔案是否為 ZIP 壓縮檔,可以使用 zipfile 的 is_zipfile 函數:
import zipfile
# 檔案名稱
files = ['a.txt', 'b.zip']
# 檢查檔案是否為 ZIP 壓縮檔
for f in files:
print('{}: {}'.format(f, zipfile.is_zipfile(f)))
a.txt: False b.zip: True
查看 ZIP 壓縮檔內容資訊
若要查看 ZIP 壓縮檔案之中有包含哪一些檔案,可以在開啟 ZIP 壓縮檔之後,使用 namelist() 函數取得檔案名稱列表:
import zipfile
# 查看 ZIP 壓縮檔內容資訊
with zipfile.ZipFile('archive.zip', 'r') as zf:
print(zf.namelist())
['build.sh', 'mount_s3.sh']
檔案名稱只是 ZIP 壓縮檔內其中一項資訊而已,其餘更詳細的資訊可以透過 infolist() 與 getinfo() 取得。
getinfo() 可以靠檔案名稱取得 ZipInfo 物件,查看詳細資訊:
import zipfile
import datetime
# 查看 ZIP 壓縮檔內容資訊
with zipfile.ZipFile('archive.zip', 'r') as zf:
# # 以檔案名稱取得 ZipInfo 物件
info = zf.getinfo('build.sh')
print(info)
# ZipInfo 物件各項資訊
print('檔案名稱:', info.filename)
print('修改時間:', datetime.datetime(*info.date_time))
print('壓縮方式:', info.compress_type)
print('未壓縮大小:', info.file_size, 'bytes')
print('壓縮後大小:', info.compress_size, 'bytes')
<ZipInfo filename='build.sh' compress_type=deflate filemode='-rw-rw-r--' file_size=885 compress_size=488> 檔案名稱: build.sh 修改時間: 2022-02-22 11:24:16 壓縮方式: 8 未壓縮大小: 885 bytes 壓縮後大小: 488 bytes
infolist() 則是可以用於取得所有檔案的 ZipInfo 物件列表:
import zipfile
# 查看 ZIP 壓縮檔內容資訊
with zipfile.ZipFile('archive.zip', 'r') as zf:
# 透過 InfoInfo 物件查看 ZIP 檔案內容
for info in zf.infolist():
print(info)
<ZipInfo filename='build.sh' compress_type=deflate filemode='-rw-rw-r--' file_size=885 compress_size=488> <ZipInfo filename='mount_s3.sh' compress_type=deflate filemode='-rwxrwxr-x' file_size=1553 compress_size=399>
建立 ZIP 壓縮檔案
若要建立 ZIP 壓縮檔案,可以先建立 ZipFile 物件之後,再以 write() 加入要壓縮的檔案:
import zipfile
# 建立 ZIP 壓縮檔
with zipfile.ZipFile('new_archive.zip', mode='w') as zf:
# 加入要壓縮的檔案
zf.write("a.txt")
zf.write("b.txt")
若要指定壓縮方式,可以加上 compression 參數:
import zipfile
# 建立 ZIP 壓縮檔,以 DEFLATED 方式壓縮
with zipfile.ZipFile('new_archive.zip', mode='w',
compression=zipfile.ZIP_DEFLATED) as zf:
# 加入要壓縮的檔案
zf.write("a.txt")
zf.write("b.txt")
直接寫入資料
若要將程式中的資料直接寫入 ZIP 壓縮檔中,可以改用 writestr() 函數,以下是一個簡單的範例:
import zipfile
# 要壓縮的資料
my_data = "Hello, World."
# 建立 ZIP 壓縮檔
with zipfile.ZipFile('new_archive.zip', mode='w') as zf:
# 加入要壓縮的資料
zf.writestr("data.txt", my_data)
在上面這個例子裡面,我們在 ZIP 壓縮檔案中建立一個新檔案 data.txt,並將 my_data 變數中的資料寫入其中。
附加新檔案
如果要在既有的 ZIP 壓縮檔案中加入新的檔案,可以將 mode 參數設為 'a',以附加模式加入新檔案:
import zipfile
# 建立 ZIP 壓縮檔
with zipfile.ZipFile('new_archive.zip', mode='w') as zf:
# 加入要壓縮的檔案
zf.write("a.txt")
# 附加新檔案
with zipfile.ZipFile('new_archive.zip', mode='a') as zf:
# 加入要壓縮的檔案
zf.write("b.txt")
解壓縮 ZIP 檔案
若要解壓縮檔案,可以使用 extract() 函數:
import zipfile
# 開啟 ZIP 壓縮檔
with zipfile.ZipFile('archive.zip', 'r') as zf:
# 列出每個檔案
for name in zf.namelist():
# 解壓縮指定檔案至 /my/folder 目錄
zf.extract(name, path='/my/folder')
這裡的 path 參數可以指定解壓縮後的檔案要放置的位置,若不指定放置路徑,則預設會放在目前所在的目錄之下。
我們也可以用 extractall() 函數一次解壓縮所有檔案至指定位置:
import zipfile
# 開啟 ZIP 壓縮檔
with zipfile.ZipFile('archive.zip', 'r') as zf:
# 解壓縮所有檔案至 /my/folder 目錄
zf.extractall(path='/my/folder')
CRC 檢查碼
在 ZIP 壓縮檔案中,每個檔案都有附帶一組 CRC 檢查碼,可用於確認每個檔案的完整性,確認檔案有無毀損,我們可以使用 testzip() 函數來檢查 ZIP 檔案內每一個檔案的 CRC 檢查碼,若有檔案的 CRC 檢查碼有問題,此函數就會傳回第一個發現的問題檔案名稱,若都正常則傳回 None。以下是一個簡單的範例:
import zipfile
# 開啟 ZIP 壓縮檔
with zipfile.ZipFile('broken_data.zip', 'r') as zf:
# 確認 CRC 檢查碼
crc_result = zf.testzip()
# 輸出第一個錯誤的檔案名稱
if crc_result:
print(crc_result)
例外處理
若遇到損毀的 ZIP 壓縮檔,在解壓縮的時候會丟出 BadZipfile 例外,以下是例外處理的範例:
import zipfile
# 開啟 ZIP 壓縮檔
with zipfile.ZipFile('broken_data.zip', 'r') as zf:
# 解壓縮
try:
zf.extractall()
except zipfile.BadZipfile as e:
print("ZIP 檔案錯誤:", e)
ZIP 檔案錯誤: Bad CRC-32 for file 'build.sh'
