【Python】Python實現解壓rar檔案

清风来叙發表於2024-06-15

Python實現解壓rar檔案

零、需求

最近在開發一個填分數的應用,需要用到selenium,那麼自然需要用到瀏覽器,瀏覽器內建到應用中,但是上傳到GitCode的時候被限制了,單個檔案大小隻能是10M以內。所以只能壓縮,分卷,用的時候再解壓就好。zip的分卷解壓要合併後才能解壓,太佔用磁碟資源了,因此用rar。7z之前用過,也比較麻煩,現在想試試rar。

壹、實現

準備工作

安裝rarfile

pip install rarfile

RAR程式

RAR不是開源的,沒有Python實現,本質還是呼叫exe解壓,故需要下載一個WinRAR,安裝WinRAR後我們在WinRAR的安裝目錄中找到UnRAR.exe,把這個複製到我們專案目錄下即可,這樣其他電腦執行我們的程式碼時不需要另外安裝WinRAR。
專案結構

程式碼實現

我們需要用到rarfile這個庫,這個庫的用法跟Python內建的zipfile用法一樣,所以學習成本幾乎為0,我們要做的就是在使用rarfile之前把UnRAR.exe新增到path環境變數中去。
我們需要把UnRAR.exe所在目錄傳入這個函式即可,這個函式不會改變系統的設定,隻影響當前程式的環境變數,新增環境變數程式碼如下:

def set_path(path:str):
    """
    新增目錄到path環境變數中
    :param path: 目錄
    :return: None
    """
    os_path = os.environ.get('path')
    if path in os_path:
        return
    else:
        if os.path.exists(path):
            os.environ['path'] = f'{os_path};{path};'
        else:
            raise ValueError('環境變數路徑不存在')

之後是解壓程式碼的實現,這個跟zipfile一樣用的:

def unrar_file(rar_file, target_path=None, password=None, progress_fun=None):
    """
    解壓rar檔案
    :param rar_file: 檔案路徑
    :param target_path: 解壓目標路徑
    :param password: 密碼
    :param progress_fun: 進度函式,會傳遞一個 0-1的進度浮點
    :return: 成功 True
    """

    # 設定環境變數
    set_path(
        get_relative_path('chrome')
    )

    # 設定密碼
    if not (password is None):
        password = password.encode('utf-8')
    logger.debug('解壓rar檔案:' + str(rar_file))

    # 開啟rar檔案
    rf = rarfile.RarFile(rar_file)
    try:
        file_list = rf.infolist()
        # 統計總大小
        all_size = 0
        for i in file_list:
            all_size += i.file_size
        # 解壓
        unrar_size = 0
        for file in file_list:
            rf.extract(file, path=target_path, pwd=password)
            unrar_size += file.file_size
            
            # 呼叫顯示進度的函式
            if progress_fun:
                progress_fun(unrar_size / all_size)
    except Exception as e:
        raise e
    finally:
        rf.close()
    return True

程式碼中get_relative_path函式是透過相對路徑獲取絕對路徑的函式,這個與本文無關就不貼出了,返回就是一個絕對路徑。程式碼中logger是日誌物件,相當於就是列印函式,可以改成print輸出。程式碼中progress_fun函式是列印進度的函式,接受一個浮點數,代表進度,這個大家可以自己實現一下,也可以直接刪除。

貳、參考文件

  • rarfile API documentation

相關文章