当前位置:首页>python>【Python办公】批量压缩/解压缩桌面工具

【Python办公】批量压缩/解压缩桌面工具

  • 2026-09-02 19:05:11
【Python办公】批量压缩/解压缩桌面工具

用 Python + PyQt5 打造一款批量压缩/解压缩桌面工具

前言

在日常办公中,我们经常需要处理大量的压缩文件——批量打包项目资料、解压客户发来的一堆附件……每次都要右键一个个操作,效率极低。

今天,我们用 Python + PyQt5 手撸一个批量压缩/解压缩桌面工具,支持 ZIP、7Z、TAR、TAR.GZ、TAR.BZ2、RAR 等主流格式,还支持拖拽添加文件,一键批量处理!

欢迎大家关注此公众号,后台留言"python书籍"可免费获取【Python办公自动化高清PDF】电子书一本

此外小庄推荐一本适合于新手\小白入手一本 Python基础书籍,欢迎大家订阅


效果预览

工具启动后是一个简洁的桌面窗口,核心功能包括:

  • • 压缩模式:选择多个文件/文件夹,一键打包成 ZIP / 7Z / TAR 等格式
  • • 解压模式:批量选择压缩包,一键全部解压
  • • 拖拽支持:直接把文件拖进窗口,省去选择的麻烦
  • • 实时日志:处理过程实时显示,一目了然
  • • 进度条:直观看到处理进度

技术栈

技术
用途
Python 3
主语言
PyQt5
GUI 桌面界面框架
zipfile
处理 ZIP 格式(标准库)
tarfile
处理 TAR/TAR.GZ/TAR.BZ2 格式(标准库)
py7zr
处理 7Z 格式(可选依赖)
rarfile
处理 RAR 格式(可选依赖)

项目结构

16-批量压缩解压缩工具/
├── main.py           # 主程序(所有逻辑都在这里)
├── requirements.txt  # 依赖清单
├── run.bat           # Windows 一键启动脚本
├── run.sh            # macOS/Linux 一键启动脚本
└── README.md         # 项目说明

整个项目只有一个 main.py,结构非常清晰,适合学习和二次开发。


核心代码解析

1. 整体架构设计

程序采用经典的 主线程 + 工作线程 架构:

┌──────────────────────┐
│   CompressorApp      │  ← 主窗口(UI 线程)
│   (QMainWindow)      │
├──────────────────────┤
│   CompressionWorker  │  ← 工作线程(后台处理)
│   (QThread)          │
└──────────────────────┘
  • • CompressorApp:负责界面展示、用户交互
  • • CompressionWorker:负责实际的压缩/解压操作,运行在独立线程中,避免界面卡顿

这是 PyQt5 开发中非常重要的设计模式——耗时操作必须放在子线程,否则 UI 会直接卡死。


2. 工作线程 CompressionWorker

这是整个工具的"引擎",继承自 QThread:

classCompressionWorker(QThread):
    progress = pyqtSignal(int)        # 进度信号(0-100)
    log = pyqtSignal(str)             # 日志信号
    finished = pyqtSignal(bool, str)  # 完成信号(是否成功, 消息)

通过 信号(Signal) 机制与主线程通信:

  • • progress 信号驱动进度条更新
  • • log 信号驱动日志区域实时输出
  • • finished 信号通知任务完成,弹出提示框

压缩功能

根据用户选择的格式,分发到不同的压缩方法:

def_compress_files(self):
ifself.format_type == "zip":
self._compress_to_zip(output_file)
elifself.format_type == "7z":
self._compress_to_7z(output_file)
elifself.format_type.startswith("tar"):
self._compress_to_tar(output_file, self.format_type)

以 ZIP 压缩为例,核心逻辑如下:

def_compress_to_zip(self, output_file: str):
with zipfile.ZipFile(output_file, 'w', zipfile.ZIP_DEFLATED) as zipf:
for idx, file_path inenumerate(self.files):
if os.path.isfile(file_path):
# 单个文件:直接写入
                zipf.write(file_path, arcname=os.path.basename(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=arcname)
# 更新进度
self.progress.emit(int((idx + 1) / total * 100))

关键细节:

  • • 使用 ZIP_DEFLATED 压缩算法,兼容性最好
  • • 文件夹通过 os.walk() 递归遍历,保持目录结构
  • • arcname 使用相对路径,确保解压后目录结构正确

解压功能

解压时根据文件后缀名自动识别格式:

def_decompress_single_file(self, file_path: str):
    filename = os.path.basename(file_path).lower()

if filename.endswith('.zip'):
with zipfile.ZipFile(file_path, 'r') as zip_ref:
            zip_ref.extractall(extract_dir)
elif filename.endswith('.7z'):
with py7zr.SevenZipFile(file_path, 'r') as archive:
            archive.extractall(path=extract_dir)
elif filename.endswith('.rar'):
with rarfile.RarFile(file_path) as rar:
            rar.extractall(path=extract_dir)
elif filename.endswith(('.tar', '.tar.gz', '.tgz', '.tar.bz2', '.tbz2')):
with tarfile.open(file_path, mode) as tar:
            tar.extractall(path=extract_dir)

每个压缩包会解压到以文件名命名的子目录中,避免文件混乱:

extract_dir = os.path.join(self.output_dir, Path(file_path).stem)

比如解压 project.zip,会解压到 输出目录/project/ 下。


3. 主窗口 CompressorApp

界面布局

界面采用纵向堆叠布局,从上到下依次是:

┌─────────────────────────────────┐
│  标题:📦 批量压缩/解压缩工具     │
├─────────────────────────────────┤
│  模式选择 | 格式选择              │
├─────────────────────────────────┤
│  📁 文件列表(支持拖拽)          │
│  ┌─────────────────────────┐    │
│  │ 📄 file1.txt            │    │
│  │ 📂 my_folder            │    │
│  └─────────────────────────┘    │
├─────────────────────────────────┤
│  [添加文件] [添加文件夹] [清空] [移除] │
├─────────────────────────────────┤
│  输出目录: /path/to/output [选择] │
├─────────────────────────────────┤
│  ████████████████░░░░ 75%       │
├─────────────────────────────────┤
│  📋 处理日志                     │
│  ┌─────────────────────────┐    │
│  │ 📦 开始压缩...           │    │
│  │   ✓ file1.txt           │    │
│  └─────────────────────────┘    │
├─────────────────────────────────┤
│         [▶ 开始处理]             │
└─────────────────────────────────┘

拖拽功能实现

拖拽是这个工具的亮点功能之一,实现也很简单:

defsetup_drag_drop(self):
self.file_list.setAcceptDrops(True)
self.file_list.dragEnterEvent = self.drag_enter_event
self.file_list.dropEvent = self.drop_event

defdrag_enter_event(self, event):
if event.mimeData().hasUrls():
        event.acceptProposedAction()  # 接受拖拽

defdrop_event(self, event):
for url in event.mimeData().urls():
        file_path = url.toLocalFile()  # 获取本地文件路径
self.add_file_item(file_path)  # 添加到列表

核心就三步:开启拖拽 → 验证是文件 URL → 转为本地路径并添加。

去重机制

添加文件时会自动去重,避免重复处理:

defadd_file_item(self, file_path: str):
if file_path notinself.selected_files:  # 检查是否已存在
self.selected_files.append(file_path)
# ... 添加到 UI 列表

模式切换

切换"压缩/解压缩"模式时,格式选择框会自动启用/禁用:

defon_mode_changed(self, mode: str):
self.format_combo.setEnabled(mode == "压缩文件")

解压模式下不需要选择格式,因为会根据文件后缀自动识别。


4. 样式美化

工具使用了 QSS(Qt Style Sheets) 进行美化,类似于 CSS:

def_get_stylesheet(self):
return"""
    QMainWindow {
        background-color: 
#ecf0f1;       /* 浅灰色背景 */
    }
    QPushButton {
        background-color: #3498db;       /* 蓝色按钮 */
        color: white;
        border: none;
        border-radius: 4px;             /* 圆角 */
        padding: 8px 12px;
        font-weight: bold;
    }
    QPushButton:hover {
        background-color: #2980b9;       /* 悬停变深 */
    }
    """

日志区域使用了深色主题,模拟终端风格:

self.log_display.setStyleSheet("""
    QTextEdit {
        background-color: #2c3e50;       /* 深色背景 */
        color: #ecf0f1;                  /* 浅色文字 */
        font-family: 'Courier New', monospace;  /* 等宽字体 */
    }
"""
)

5. 可选依赖的优雅处理

对于 py7zr 和 rarfile 这两个非必须的依赖,代码使用了 try-except 做了优雅降级:

try:
import py7zr
except ImportError:
    py7zr = None

try:
import rarfile
except ImportError:
    rarfile = None

在实际使用时,如果用户没安装这些库,会给出友好提示而不是直接崩溃:

def_compress_to_7z(self, output_file):
if py7zr isNone:
self.log.emit("❌ 需要安装 py7zr: pip install py7zr")
return

如何运行

1. 安装依赖

pip install -r requirements.txt

核心依赖只有 PyQt5,可选安装 py7zr(支持 7Z)和 rarfile(支持 RAR)。

2. 启动程序

python main.py

或者直接双击 run.bat(Windows)/ run.sh(macOS/Linux)。


使用指南

压缩文件

  1. 1. 模式选择"压缩文件"
  2. 2. 选择压缩格式(ZIP / 7Z / TAR 等)
  3. 3. 点击"添加文件"或"添加文件夹",也可以直接拖拽文件到列表
  4. 4. 选择输出目录
  5. 5. 点击"开始处理"

压缩包会以 compressed_20260411_143000.zip 这样的时间戳命名,不会覆盖旧文件。

解压文件

  1. 1. 模式选择"解压缩文件"
  2. 2. 添加需要解压的压缩包(支持 ZIP/7Z/RAR/TAR 等)
  3. 3. 选择输出目录
  4. 4. 点击"开始处理"

每个压缩包会解压到独立的子目录中,互不干扰。


可扩展方向

这个工具虽然功能已经比较完善,但还有很多可以扩展的方向:

  1. 1. 加密压缩:支持设置密码保护
  2. 2. 压缩级别:让用户选择压缩率(速度优先 vs 体积优先)
  3. 3. 分卷压缩:大文件自动分卷
  4. 4. 右键菜单集成:注册到系统右键菜单
  5. 5. 压缩包预览:不解压直接查看压缩包内容
  6. 6. 多语言支持:国际化

总结

这个项目麻雀虽小,五脏俱全,涵盖了 PyQt5 桌面开发中的多个核心知识点:

知识点
对应实现
多线程
QThread + Signal/Slot 机制
拖拽功能
dragEnterEvent + dropEvent
文件操作
zipfile / tarfile / py7zr / rarfile
样式美化
QSS 样式表
布局管理
QVBoxLayout + QHBoxLayout 嵌套
用户交互
QFileDialog / QMessageBox
进度反馈
QProgressBar + 实时日志

如果你正在学习 Python GUI 开发,这个项目是一个非常好的练手项目。代码量不大,但覆盖面广,建议动手跑一跑、改一改,一定会有收获!

最新文章

随机文章