Categories: Python

Python 使用 zipfile 模組壓縮、解壓縮 ZIP 檔案教學與範例

介紹如何使用 Python 的 zipfile 模組,壓縮與解壓縮 ZIP 檔案,並查看 ZIP 檔案資訊。

Python 標準函式庫中的 zipfile 模組可以用來壓縮與解壓縮 ZIP 檔案,以下是使用的教學與範例。

檢查檔案是否為 ZIP 壓縮檔

若要檢查指定的檔案是否為 ZIP 壓縮檔,可以使用 zipfileis_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'

參考資料

Share
Published by
Office Guide

Recent Posts

Python 使用 PyAutoGUI 自動操作滑鼠與鍵盤

本篇介紹如何在 Python ...

1 年 ago

Ubuntu Linux 以 WireGuard 架設 VPN 伺服器教學與範例

本篇介紹如何在 Ubuntu ...

1 年 ago

Linux 網路設定 ip 指令用法教學與範例

本篇介紹如何在 Linux 系...

1 年 ago

Linux 以 Cryptsetup、LUKS 加密 USB 隨身碟教學與範例

介紹如何在 Linux 系統中...

1 年 ago