在日常办公中,我们经常需要处理大量的压缩文件——批量打包项目资料、解压客户发来的一堆附件……每次都要右键一个个操作,效率极低。
今天,我们用 Python + PyQt5 手撸一个批量压缩/解压缩桌面工具,支持 ZIP、7Z、TAR、TAR.GZ、TAR.BZ2、RAR 等主流格式,还支持拖拽添加文件,一键批量处理!

欢迎大家关注此公众号,后台留言"python书籍"可免费获取【Python办公自动化高清PDF】电子书一本
此外小庄推荐一本适合于新手\小白入手一本 Python基础书籍,欢迎大家订阅
工具启动后是一个简洁的桌面窗口,核心功能包括:
16-批量压缩解压缩工具/
├── main.py # 主程序(所有逻辑都在这里)
├── requirements.txt # 依赖清单
├── run.bat # Windows 一键启动脚本
├── run.sh # macOS/Linux 一键启动脚本
└── README.md # 项目说明整个项目只有一个 main.py,结构非常清晰,适合学习和二次开发。
程序采用经典的 主线程 + 工作线程 架构:
┌──────────────────────┐
│ CompressorApp │ ← 主窗口(UI 线程)
│ (QMainWindow) │
├──────────────────────┤
│ CompressionWorker │ ← 工作线程(后台处理)
│ (QThread) │
└──────────────────────┘这是 PyQt5 开发中非常重要的设计模式——耗时操作必须放在子线程,否则 UI 会直接卡死。
这是整个工具的"引擎",继承自 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/ 下。
界面采用纵向堆叠布局,从上到下依次是:
┌─────────────────────────────────┐
│ 标题:📦 批量压缩/解压缩工具 │
├─────────────────────────────────┤
│ 模式选择 | 格式选择 │
├─────────────────────────────────┤
│ 📁 文件列表(支持拖拽) │
│ ┌─────────────────────────┐ │
│ │ 📄 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 == "压缩文件")解压模式下不需要选择格式,因为会根据文件后缀自动识别。
工具使用了 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; /* 等宽字体 */
}
""")对于 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")
returnpip install -r requirements.txt核心依赖只有 PyQt5,可选安装 py7zr(支持 7Z)和 rarfile(支持 RAR)。
python main.py或者直接双击 run.bat(Windows)/ run.sh(macOS/Linux)。
压缩包会以 compressed_20260411_143000.zip 这样的时间戳命名,不会覆盖旧文件。
每个压缩包会解压到独立的子目录中,互不干扰。
这个工具虽然功能已经比较完善,但还有很多可以扩展的方向:
这个项目麻雀虽小,五脏俱全,涵盖了 PyQt5 桌面开发中的多个核心知识点:
如果你正在学习 Python GUI 开发,这个项目是一个非常好的练手项目。代码量不大,但覆盖面广,建议动手跑一跑、改一改,一定会有收获!