Python案例怎么压缩本地文件夹?

wen python案例 60

Python案例实战指南(附完整代码)

目录导读

  1. 为什么要用Python压缩文件夹?
  2. 核心库选择:zipfile与shutil的对比分析
  3. 实战案例一:基础文件夹压缩(zip格式)
  4. 实战案例二:带密码保护与分卷压缩的高级方案
  5. 实战案例三:跨平台兼容性与异常处理优化
  6. 常见问题与解决方案(Q&A)
  7. SEO优化建议与性能调优技巧

为什么要用Python压缩文件夹?

在日常开发与运维工作中,我们经常需要批量处理文件:备份项目代码、归档日志文件、传输数据包等,手动右键压缩不仅效率低下,而且难以在自动化流程中集成,Python作为脚本语言之王,提供了zipfileshutiltarfilepy7zr等多个库来满足不同压缩需求。

Python案例怎么压缩本地文件夹?

核心优势

  • 自动化:结合定时任务(如cron)实现定期备份
  • 跨平台:Windows/Linux/macOS代码一致
  • 灵活扩展:支持密码、分卷、多线程等高级特性
  • 节省空间:可自定义压缩级别与文件过滤规则

核心库选择:zipfile与shutil的对比分析

特性 zipfile shutil.make_archive tarfile
适用场景 精细控制单个文件 快速打包整个目录 Linux环境兼容
密码支持 支持(需第三方库) 不支持 支持
压缩格式 zip zip,tar,gztar,bztar tar.gz,tar.bz2
层级控制 手动遍历文件 自动递归 自动递归
性能 中等 高(C底层优化)

对于初学者,shutil.make_archive是最快捷的方式;如果需要密码保护或文件过滤,推荐zipfile;在Linux服务器上,tarfile是标准选择。

实战案例一:基础文件夹压缩(zip格式)

import os
import zipfile
from pathlib import Path
def compress_folder_to_zip(source_folder, output_zip):
    """
    压缩整个文件夹为zip文件
    :param source_folder: 源文件夹路径
    :param output_zip: 输出zip文件路径
    """
    source_folder = Path(source_folder)
    with zipfile.ZipFile(output_zip, 'w', zipfile.ZIP_DEFLATED) as zf:
        for file_path in source_folder.rglob('*'):
            if file_path.is_file():
                # 在zip中保持相对路径
                arcname = file_path.relative_to(source_folder.parent)
                zf.write(file_path, arcname)
# 使用示例
compress_folder_to_zip('/home/user/project', 'backup.zip')

关键点

  • rglob('*')递归获取所有文件
  • ZIP_DEFLATED启用压缩(默认为存储模式)
  • relative_to保留文件夹层级结构

实战案例二:带密码保护与分卷压缩的高级方案

许多企业需要加密传输文件,我们利用pyzipper库实现AES-256加密:

import pyzipper
def encrypt_folder(source_folder, output_zip, password):
    """
    加密压缩文件夹(AES-256)
    """
    with pyzipper.AESZipFile(output_zip, 'w', encryption=pyzipper.WZ_AES) as zf:
        zf.setpassword(password.encode('utf-8'))
        for root, dirs, files in os.walk(source_folder):
            for file in files:
                file_path = os.path.join(root, file)
                arcname = os.path.relpath(file_path, source_folder)
                zf.write(file_path, arcname)
# 使用
encrypt_folder('data', 'encrypted_backup.zip', 'MySecurePassword2024')

分卷压缩实现(利用split_zipfile库或手动分割):

import zipfile
import math
def split_zip(source_folder, output_prefix, max_size_mb=100):
    """分卷压缩:每个卷最大100MB"""
    max_bytes = max_size_mb * 1024 * 1024
    current_size = 0
    part_num = 0
    zf = None
    for root, dirs, files in os.walk(source_folder):
        for file in files:
            file_path = os.path.join(root, file)
            file_size = os.path.getsize(file_path)
            # 如果当前卷超过限制,创建新卷
            if zf is None or current_size + file_size > max_bytes:
                if zf:
                    zf.close()
                part_num += 1
                part_name = f"{output_prefix}.part{part_num}.zip"
                zf = zipfile.ZipFile(part_name, 'w', zipfile.ZIP_DEFLATED)
                current_size = 0
            arcname = os.path.relpath(file_path, source_folder)
            zf.write(file_path, arcname)
            current_size += file_size
    if zf:
        zf.close()
    print(f"分卷完成,共{part_num}个文件")

实战案例三:跨平台兼容性与异常处理优化

import logging
import sys
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
def safe_compress(folder_path, output_path, exclude_ext=None):
    """
    安全压缩:自动处理路径分隔符、权限问题、中文文件名
    :param folder_path: 源文件夹
    :param output_path: 输出zip
    :param exclude_ext: 排除的文件扩展名列表 ['tmp', 'log']
    """
    try:
        folder_path = Path(folder_path).resolve()
        if not folder_path.exists():
            raise FileNotFoundError(f"源文件夹不存在: {folder_path}")
        # Windows路径兼容转换
        output_path = output_path.replace('\\', '/')
        with zipfile.ZipFile(output_path, 'w', zipfile.ZIP_DEFLATED) as zf:
            for file_path in folder_path.rglob('*'):
                if file_path.is_file():
                    # 跳过排除文件
                    if exclude_ext and file_path.suffix.lstrip('.') in exclude_ext:
                        continue
                    # 使用UTF-8编码文件名避免乱码
                    arcname = file_path.relative_to(folder_path.parent)
                    arcname = str(arcname).encode('utf-8').decode('utf-8')
                    try:
                        zf.write(file_path, arcname)
                        logging.info(f"已添加: {arcname}")
                    except PermissionError:
                        logging.warning(f"跳过无权限文件: {file_path}")
        logging.info(f"压缩完成: {output_path} (大小: {os.path.getsize(output_path)/1024:.1f} KB)")
        return True
    except Exception as e:
        logging.error(f"压缩失败: {str(e)}")
        if os.path.exists(output_path):
            os.remove(output_path)  # 清理不完整的压缩文件
        return False
# 使用
safe_compress('/var/log/myapp', 'logs_backup.zip', exclude_ext=['tmp', 'swp'])

常见问题与解决方案(Q&A)

Q1: 压缩后的文件在Windows下乱码怎么办? A: 确保使用zipfile.ZipFile时指定utf-8编码,如果使用shutil.make_archive,请在Windows系统上安装chardet库并检测原系统编码,推荐统一使用pathlib处理路径。

Q2: 如何只压缩特定类型的文件(如只压缩.py和.txt)? A: 在遍历文件时添加过滤条件:

if file_path.suffix in ['.py', '.txt', '.md']:
    zf.write(file_path, arcname)

Q3: 压缩超大文件夹(超过4GB)时出错? A: zip格式有4GB文件大小限制(ZIP64格式可突破),建议:1)使用zipfile.ZIP64模式;2)改用tar.gz格式;3)分卷压缩,注意Python3.4+默认支持ZIP64。

Q4: 压缩速度太慢怎么优化? A: 1)使用threading多线程并行压缩;2)降低压缩级别(ZIP_STORED仅存储不压缩);3)先用os.scandir快速扫描文件;4)对大文件使用流式处理而非一次性加载。

Q5: 能否在压缩中删除原文件? A: 可以在压缩成功后添加:

import shutil
shutil.rmtree(source_folder)  # 谨慎使用

SEO优化建议与性能调优技巧

代码优化要点

  1. 使用pathlib替代os.path,代码更简洁且跨平台
  2. 善用生成器表达式减少内存占用
  3. 对大目录使用os.scandir代替os.listdir
  4. 压缩级别设为ZIP_DEFLATED(默认)平衡速度与大小
  5. 缓存os.path.getsize结果避免重复调用

搜索引擎优化小贴士

  • 文章中的代码块使用<pre>标签并设置lang="python"
  • 外部链接使用nofollow属性(本文已按要求替换所有域名指向示例)
  • 添加结构化数据标记(FAQ Schema)提升搜索结果展示
  • 核心关键词自然分布在H2/H3标题中(如"Python压缩文件夹")

扩展阅读建议

  • 官方文档:Python zipfile模块文档
  • 安全实践:压缩路径遍历攻击防护(避免等危险路径)
  • 替代方案:使用7-Zip的命令行接口通过subprocess实现更高压缩率

本文从基础到高级,系统讲解了使用Python压缩本地文件夹的多种方案,从最简单的shutil.make_archive一行代码,到支持AES-256加密与分卷压缩的企业级实现,再到跨平台异常处理的完整解决方案,无论你是需要自动化备份的运维工程师,还是搭建云存储工具的开发者,这些案例都能直接应用于实际生产环境,选择哪种方案取决于你的具体场景:快速开发用shutil,安全加密用pyzipper,Linux服务器首选tarfile,动手实践时,不妨从我们的安全压缩函数开始,逐步添加到你的自动化脚本中。

抱歉,评论功能暂时关闭!