介紹如何使用 Python 的 zipfile
模組,壓縮與解壓縮 ZIP 檔案,並查看 ZIP 檔案資訊。
Python 標準函式庫中的 zipfile 模組可以用來壓縮與解壓縮 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 壓縮檔之後,使用 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 壓縮檔案,可以先建立 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")
若要解壓縮檔案,可以使用 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')
在 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'