python zip打包压缩和解压文件

压缩

1、自定义公共函数zip_files_and_dirs

import os
import zipfile


# 递归检测文件文件是否存在,存在则重命名文件
def check_file_exists(check_file, original_file=None, num=1):
    if os.path.exists(check_file):
        original_file = original_file if original_file else check_file
        _splitext = os.path.splitext(original_file)
        new_file_name = _splitext[0] + str(num) + _splitext[1]
        new_file_name = check_file_exists(new_file_name, original_file, num + 1)
        return new_file_name
    return check_file


def zip_files_and_dirs(file_path_list, target_dir=None, target_file_name=None):
    # 确保目标目录存在
    assert file_path_list, "zip_files_and_dirs fail. params file_path_list is blank."

    if not target_dir:
        dir_path = file_path_list[0]
        target_dir = os.path.dirname(dir_path)
    if not target_file_name:
        dir_path = os.path.splitext(file_path_list[0])[0]
        target_file_name = os.path.basename(dir_path)
    # 确保目标目录存在
    if not os.path.exists(target_dir):
        os.makedirs(target_dir)

    # 创建zip文件的完整路径
    zip_path = os.path.join(target_dir, f"{target_file_name}.zip")
    zip_path = check_file_exists(zip_path)  # 检测文件是否存在
    # 创建zip文件
    with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
        for file_path in file_path_list:
            if os.path.isfile(file_path):
                # 如果是文件,直接添加到zip中
                zipf.write(file_path, os.path.relpath(file_path, os.path.dirname(file_path)))
            elif os.path.isdir(file_path):
                # 如果是目录,递归添加目录及其子内容
                for root, dirs, files in os.walk(file_path):
                    for file in files:
                        file_full_path = os.path.join(root, file)
                        arcname = os.path.relpath(file_full_path, os.path.dirname(file_path))
                        zipf.write(file_full_path, arcname)

                    # 确保即使目录为空也被添加
                    if not files and not dirs:
                        arcname = os.path.relpath(root, os.path.dirname(file_path)) + '/'
                        zipf.writestr(arcname, '')

    return zip_path


if __name__ == '__main__':
    # 存放目录或文件的列表
    _file_path_list = [r'D:\ljh\project\test\test_path\new',  // 存有子文件和子目录
                       r'D:\ljh\project\test\test_path\test_dir',  // 空目录
                       r'D:\ljh\project\test\test_path\docx_file.docx',  
                       r'D:\ljh\project\test\test_path\test.txt']

    _target_dir = r'D:\ljh\project\test\test_path\target_dir'  //压缩后目标目录
    _zip_path = zip_files_and_dirs(_file_path_list, _target_dir, 'output') // 压缩打包, 'output'为压缩的文件名(output.zip)
    print(f"ZIP 文件已创建:{_zip_path}")

2、输出结果:

ZIP 文件已创建:D:\ljh\project\test\test_path\target_dir\output.zip

解压

import os
import shutil
import zipfile


def support_gbk(zip_file: zipfile.ZipFile):
    name_to_info = zip_file.NameToInfo
    # copy map first
    for name, info in name_to_info.copy().items():
        try:
            real_name = name.encode('cp437').decode('gbk')
        except Exception as _e:
            _ = _e
            real_name = name.encode('utf8').decode('utf8')
        if real_name != name:
            info.filename = real_name
            del name_to_info[name]
            name_to_info[real_name] = info
    return zip_file


def unzip_files(file_zip_path):
    save_path = os.path.dirname(file_zip_path)
    dir_path = os.path.splitext(file_zip_path)[0]
    if os.path.isdir(dir_path):
        shutil.rmtree(dir_path)
    with support_gbk(zipfile.ZipFile(file_zip_path)) as zip_ref:
        zip_ref.extractall(save_path)
    return save_path

if __name__ == '__main__':
    _zip_file = r"D:\ljh\project\test\test_path\target_dir\output.zip"
    _un_zip_path = unzip_files(_zip_file)
    print(_un_zip_path)
posted @ 2024-11-22 16:38  二月雪  阅读(6)  评论(0编辑  收藏  举报