2021年1月30日 星期六

Python 學習筆記 : 用 zipfile 模組壓縮與解壓縮 zip 檔

在 "Python 程式超入門 (旗標, 鎌田正浩, 2016)" 這本書的第四章介紹了如何使用 zipfile 這個內建的標準函式庫來壓縮與解壓縮 zip 檔, 今天就來實測一下吧!  套件 zipfile 的說明文件參考 :


書上建議到 Python 官網下載一個 zip 檔來測試 (大小約為 5.7MB) :


下載之後將此 python-3.5.1-embed-win32.zip 檔放到工作目錄下, 例如 D:\test\python 下, 就可以開始測試了. 因為 zipfile 是內建模組, 所以 zipfile 可以直接匯入使用 :

import zipfile 

測試紀錄如下 : 


1. 解壓縮檔案 : 

壓縮檔案有 3 個步驟 : 

(1). 呼叫 zipfile.ZipFile("欲解壓縮之 zip 檔檔名"), 它會傳回一個 ZipFile 物件
(2). 呼叫 ZipFile 物件的 extract("欲解壓縮之檔案名稱", r"存放目錄") 方法
(3). 呼叫 close() 方法關閉 ZipFile 物件

如果要解壓縮全部檔案, 則要呼叫 extractall(r"存放目錄"). ZipFile() 函數其實有一個第二參數 mode, 其預設值為 'r' (讀取 zip 檔, 即解壓縮模式), 要壓縮檔案時須使用 mode='w', 要添加檔案到 zip 檔則使用 mode='a'. 

呼叫 zipfile 模組的 ZipFile("zip 檔名") 函數並傳入要解壓縮之 zip 檔之檔名 (含路徑), 它會傳回一個 ZipFile 物件 :

>>> import zipfile  
>>> files=zipfile.ZipFile("python-3.5.1-embed-win32.zip")     
>>> files    
<zipfile.ZipFile filename='python-3.5.1-embed-win32.zip' mode='r'>

可見傳回了一個 ZipFile 物件, 呼叫此物件之 namelist('filename') 方法會傳回一個由 zip 內被壓縮檔案名稱組成的串列 :

>>> files.namelist()    
['pyexpat.pyd', 'python.exe', 'python3.dll', 'python35.dll', 'python35.zip', 'pythonw.exe', 'pyvenv.cfg', 'select.pyd', 'sqlite3.dll', 'unicodedata.pyd', 'vcruntime140.dll', 'winsound.pyd', '_bz2.pyd', '_ctypes.pyd', '_decimal.pyd', '_elementtree.pyd', '_hashlib.pyd', '_lzma.pyd', '_msi.pyd', '_multiprocessing.pyd', '_overlapped.pyd', '_socket.pyd', '_sqlite3.pyd', '_ssl.pyd']

呼叫 ZipFile 物件的 extract('extracted_file', r'folder') 方法可將欲解壓縮的檔案 (第一參數) 解壓縮至指定的目錄下, 其中目錄字串前面要冠 r 表示此為 raw 字串, 這是必要的, 沒有冠 r 會出現執行錯誤. 例如解壓縮其中的 sqlite3.dll 檔案 :

>>> files.extract('sqlite3.dll', r'.')       # 將 sqlite3.dll 接壓縮至目前目錄下
'sqlite3.dll'  

此處解壓縮目錄字串 r'.' 中的一個點號表示目前的工作目錄, 檢查檔案總管確實多了一個 sqlite3.dll 檔, 重複執行此指令會蓋掉原先的檔案而不會出現詢問或錯誤訊息. 此指令亦可明確指定目錄, 例如 :

>>> files.extract('sqlite3.dll', r'd:\test\python')    
'd:\\test\\python\\sqlite3.dll' 

雖然與上面效果相同, 但傳回值不同 (帶了路徑資訊). 

呼叫 extractall(r'folder') 方法則可以解壓縮全部檔案於指定目錄下 (該目錄若不存在會自動建立), 例如 : 

>>> files.extractall(r'd:\test\python\foo')   

檢查檔案總管檔案確實在解壓縮後放在 d:\test\python\foo 下, 該 foo 目錄為自動建立. 




解壓縮完畢須呼叫 close() 關閉檔案物件以清除所占用之資源 :

>>> files.close() 


2. 壓縮檔案 : 

壓縮檔案有 3 個步驟 : 

(1). 呼叫 zipfile.ZipFile(r"zip 檔檔名", mode="w"), 它會傳回一個 ZipFile 物件
(2). 呼叫 ZipFile 物件的 write(r"欲壓縮之檔案名稱", "檔案標題") 方法
(3). 呼叫 close() 方法關閉 ZipFile 物件

注意, "zip 檔檔名" 字串前面要冠 r.

例如要將上面解壓縮到 d:\test\python\foo 目錄下的 sqlite3.dll 壓縮成 tmp.zip :

>>> tmpzip=zipfile.ZipFile(r"d:\test\python\foo\tmp.zip", mode="w")  
>>> tmpzip.write(r"d:\test\python\foo\sqlite3.dll", "sqlite3.dll")   
>>> tmpzip.close()     

注意,  write() 方法的第二參數為 namelist() 回傳串列中的檔案標題. 這時檢查 foo 目錄下確實產生了一個 tmp.zip 壓縮檔, 用佳壓縮程式開啟可知裡面有一個檔案 :




如果要在 tmp.zip 中添加檔案, 則再次呼叫 ZipFile() 開啟 zip 檔時要傳入第二參數 mode='a'. 

用 ZipFile() 函數開啟此 tmp.zip 後再呼叫 namelist() 可看到 zip 檔內檔案之標題, 例如 :

>>> files=zipfile.ZipFile(r"d:\test\python\foo\tmp.zip")    
>>> files.namelist()    
['sqlite3.dll']

串列中的顯示的就是上面呼叫 write() 時所傳進去的第二參數.

沒有留言 :