基于Python+PyQt5开发的Windows磁盘分析与清理工具
作者:donoot
项目概述
SysDriMan 是一款基于 Python 和 PyQt5 开发的 Windows 磁盘分析与清理工具,旨在帮助用户快速了解磁盘空间使用情况,管理大文件和已安装软件,清理系统垃圾文件。
项目地址:https://github.com/donoot/SysDriMan

功能特性
1. 磁盘空间分析
- 饼图可视化:直观展示磁盘空间分布情况
- 递归浏览:双击饼图扇区可进入子目录查看详细分布
- 空间信息显示:实时显示总空间、已用空间、剩余空间
2. 大文件管理
- 自动扫描:扫描并列出大于指定阈值的大文件
- 文件详情:显示文件路径、大小、修改时间、创建时间
- 列宽可调:表格列宽支持鼠标拖动调节
3. 已安装软件管理
- 注册表读取:从 Windows 注册表读取所有已安装软件
- 快速操作:右键菜单支持卸载和修改软件
4. 垃圾文件清理
- 自动扫描:扫描系统临时目录、回收站等常见垃圾位置
- 一键清理:支持批量清理选中的垃圾文件(移至回收站)
5. 流光进度条
- 滚动渐变:参考经典工具"溯雪"的流光效果
- 实时百分比:中间显示扫描进度百分比

技术架构设计
整体架构

编辑模块划分
| 模块 | 职责 | 文件 |
|---|---|---|
| 主窗口 | UI 界面构建和功能集成 | main.py |
| 工具函数 | 管理员权限检查、文件大小格式化 | utils.py |
| 扫描线程 | 后台磁盘扫描、多线程并行处理 | scan_thread.py |
| 软件管理 | 注册表读取、软件卸载 | software_manager.py |
| 垃圾清理 | 垃圾文件扫描、清理 | garbage_cleaner.py |
核心技术实现
1. 多线程并行扫描
问题背景:磁盘扫描是一个耗时操作,如果在主线程中执行会导致 UI 卡顿。
解决方案:使用 Python threading 模块结合 Qt 的 QThread 实现多线程并行扫描。
class ScanWorker(threading.Thread): """扫描工作线程类""" def __init__(self, task_queue, result_queue, size_threshold, stop_event): super().__init__() self.task_queue = task_queue self.result_queue = result_queue self.size_threshold = size_threshold self.stop_event = stop_event def run(self): while not self.stop_event.is_set(): try: dirpath, dirnames, filenames = self.task_queue.get(timeout=1) except: break dir_size = 0 big_files = [] for f in filenames: try: fp = os.path.join(dirpath, f) if os.path.isfile(fp): st = os.stat(fp) size = st.st_size dir_size += size if size >= self.size_threshold: big_files.append((fp, size, ...)) except (PermissionError, OSError): continue self.result_queue.put((dirpath, dir_size, big_files)) self.task_queue.task_done()
关键设计:
- 使用
Queue实现任务分发和结果收集 - 多个
ScanWorker线程并行处理目录扫描 - 通过
stop_event实现优雅停止 - 使用 Qt 信号机制向主线程传递进度
2. 流光进度条实现

问题背景:用户希望进度条具有流动的视觉效果,类似于经典工具"溯雪"中的流光效果。
解决方案:使用 QTimer 定时更新 QProgressBar 的样式表,实现滚动渐变效果。
def setup_flow_progress_style(self):
"""设置流光进度条样式"""
self.flow_gradient_pos = 0
self.flow_timer = QTimer(self)
self.flow_timer.timeout.connect(self.update_flow_animation)
base_style = """
QProgressBar {
border: 1px solid #666666;
border-radius: 4px;
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 #4a4a4a, stop:0.5 #3d3d3d, stop:1 #333333);
text-align: center;
color: #00ffff;
font-weight: bold;
font-size: 12px;
}
QProgressBar::chunk {
border-radius: 3px;
margin: 1px;
}
"""
self.progress_bar.setStyleSheet(base_style)
def update_flow_animation(self):
"""更新流光动画"""
self.flow_gradient_pos = (self.flow_gradient_pos + 1) % 100
p = self.flow_gradient_pos / 100.0
style = f"""
QProgressBar::chunk {{
background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
stop:{(p - 0.3) % 1} transparent,
stop:{(p - 0.2) % 1} rgba(0, 200, 255, 0.3),
stop:{(p - 0.1) % 1} rgba(0, 220, 255, 0.6),
stop:{p % 1} rgba(0, 255, 255, 1),
stop:{(p + 0.1) % 1} rgba(0, 220, 255, 0.6),
stop:{(p + 0.2) % 1} rgba(0, 200, 255, 0.3),
stop:{(p + 0.3) % 1} transparent);
}}
"""
self.progress_bar.setStyleSheet(style)关键设计:
- 使用
rgba颜色值实现透明度渐变 - 通过取模运算实现无缝循环
- 50ms 定时器间隔保证动画流畅
3. Matplotlib 饼图嵌入 Qt 界面
问题背景:需要在 PyQt5 界面中嵌入交互式饼图,支持双击进入子目录。
解决方案:使用 FigureCanvasQTAgg 将 Matplotlib 图表嵌入 Qt 界面,并绑定鼠标事件。
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
class MainWindow(QMainWindow):
def __init__(self):
...
self.fig = Figure(figsize=(5, 5))
self.canvas = FigureCanvas(self.fig)
self.left_layout.addWidget(self.canvas)
self.canvas.mpl_connect('button_press_event', self.on_pie_click)
def on_pie_click(self, event):
"""处理饼图双击事件"""
if event.dblclick and hasattr(self, 'wedges'):
for i, wedge in enumerate(self.wedges):
if wedge.contains(event)[0]:
label = self.pie_labels[i]
if label == '其他目录':
return
new_path = os.path.join(self.current_path, label)
if os.path.isdir(new_path):
self.path_history.append(self.current_path)
self.current_path = new_path
self.update_pie_chart()
break关键设计:
- 使用
FigureCanvasQTAgg作为 Qt 控件 - 通过
mpl_connect绑定鼠标事件 - 使用
wedge.contains(event)判断点击位置 - 维护路径历史支持返回上层
4. 管理员权限自动提升
问题背景:访问系统目录和注册表需要管理员权限,普通用户运行会遇到权限不足问题。
解决方案:在程序启动时检查权限,若无管理员权限则自动提升。
import ctypes
import sys
def is_admin():
"""检查当前进程是否以管理员身份运行"""
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False
def run_as_admin():
"""以管理员身份重新启动程序"""
if sys.platform == 'win32':
script = os.path.abspath(sys.argv[0])
params = ' '.join(['"' + arg + '"' for arg in sys.argv[1:]])
ctypes.windll.shell32.ShellExecuteW(
None, "runas", sys.executable,
f'"{script}" {params}', None, 1
)
if __name__ == "__main__":
if not is_admin():
run_as_admin()
sys.exit(0)
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())关键设计:
- 使用
IsUserAnAdmin()检查权限 - 使用
ShellExecuteW以runas方式启动 - 保留命令行参数传递
5. 中文字体配置
问题背景:Matplotlib 默认不支持中文,中文标签会显示为方块或乱码。
解决方案:检测系统可用字体并配置 Matplotlib 使用中文字体。
import matplotlib.font_manager as fm def setup_matplotlib_font(): """设置matplotlib中文字体""" available_fonts = [f.name for f in fm.fontManager.ttflist] preferred_fonts = [ 'SimHei', 'Microsoft YaHei', 'SimSun', 'KaiTi', 'Heiti SC', 'STHeiti' ] selected_font = None for font in preferred_fonts: if font in available_fonts: selected_font = font break if selected_font: matplotlib.rcParams['font.sans-serif'] = [selected_font] matplotlib.rcParams['font.family'] = 'sans-serif' matplotlib.rcParams['axes.unicode_minus'] = False setup_matplotlib_font()
关键设计:
- 枚举系统可用字体列表
- 按优先级选择最合适的中文字体
- 关闭 Unicode 负号替换
遇到的问题与解决方案
问题 1:QProgressBar 样式频繁更新导致闪烁
现象:每次更新进度条样式表时,界面会出现短暂闪烁。
原因:频繁调用 setStyleSheet 会触发控件重绘。
解决方案:
- 初始化时设置基础样式,动画更新时只修改
::chunk部分 - 使用
QTimer控制更新频率(50ms)
问题 2:多线程资源竞争
现象:多个线程同时写入结果字典时可能出现数据不一致。
原因:Python 的字典不是线程安全的。
解决方案:
- 使用
Queue收集结果,在主线程中汇总 - 避免多个线程直接修改共享数据结构
问题 3:Windows 控制台中文乱码
现象:程序输出的中文路径在控制台显示为乱码。
原因:Windows 控制台默认使用 GBK 编码,而 Python 使用 UTF-8。
解决方案:
if sys.platform == 'win32': ctypes.windll.kernel32.SetConsoleCP(65001) ctypes.windll.kernel32.SetConsoleOutputCP(65001) os.environ['PYTHONUTF8'] = '1'
问题 4:Matplotlib 饼图标签重叠
现象:当目录名称较长时,饼图标签会重叠。
解决方案:
- 设置
labeldistance=1.15增加标签距离 - 使用较小的字体大小(8-10pt)
- 限制显示的目录数量(前 10 个 + 其他)
项目运行
环境要求
| 依赖 | 安装命令 |
|---|---|
| PyQt5 | pip install PyQt5 |
| Matplotlib | pip install matplotlib |
| psutil | pip install psutil |
| send2trash | pip install send2trash |
启动方式
cd src python main.py
注意:程序会自动检查管理员权限,若无权限会弹出 UAC 提示。
总结与展望
已实现功能
- ✅ 磁盘空间分析与可视化
- ✅ 多线程并行扫描
- ✅ 流光进度条动画
- ✅ 大文件管理
- ✅ 软件管理(注册表读取、卸载)
- ✅ 垃圾文件清理
- ✅ 管理员权限自动提升
- ✅ 中文路径支持
未来计划
- 🔲 添加磁盘健康检测功能
- 🔲 支持导出分析报告(PDF/Excel)
- 🔲 添加文件类型统计
- 🔲 优化扫描算法,支持增量扫描
- 🔲 添加快捷键支持
- 🔲 支持深色/浅色主题切换
结语
SysDriMan 项目展示了如何使用 PyQt5 构建功能完善的桌面应用,涵盖了多线程编程、数据可视化、系统权限管理等多个技术要点。希望本文能对正在学习 PyQt5 开发的小伙伴有所帮助!
以上就是基于Python和PyQt5开发的Windows磁盘分析与清理工具的详细内容,更多关于PyQt5 Windows磁盘分析与清理工具的资料请关注脚本之家其它相关文章!
