Python项目73:自动化文件备份系统1.0(tkinter)
主要功能说明:
1.界面组件:源文件夹和目标文件夹选择(带浏览按钮),备份间隔时间设置(分钟),立即备份按钮,自动备份切换按钮,状态栏显示备份状态。
2.进度条显示:使用ttk.Progressbar实现精确进度显示,根据实际文件数量更新进度,实时显示已复制文件数量。
3.文件过滤功能:包含:*.docx, *.xlsx,排除:temp, ~$,支持包含/排除模式(支持通配符)。
4.日志记录系统:自动生成backup_log.txt,记录每次备份的详细信息,支持查看日志窗口(带滚动条)。
5.增量备份选项:通过MD5哈希比较文件内容,仅复制修改过的文件,可切换完整/增量备份模式。
6.使用说明:设置源目录和目标目录,配置过滤规则(可选),选择备份模式(完整/增量),设置自动备份间隔,通过按钮执行立即备份或自动备份,可随时查看备份日志。使用独立线程进行自动备份,避免界面卡顿,自动生成带时间戳的备份目录,实时状态反馈,错误处理机制。
7.注意事项:需要确保目标驱动器有足够空间,长时间运行的自动备份建议在后台运行,第一次使用时建议先进行手动备份测试,增量备份基于文件内容比对,大文件可能会影响性能,过滤规则支持标准shell通配符语法,日志文件保存在程序运行目录,进度条精度取决于文件数量而非大小。
# -*- coding: utf-8 -*-
# @Author : 小红牛
# 微信公众号:WdPython
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
import shutil
import os
from datetime import datetime
import threading
import time
import fnmatch
import hashlibclass BackupApp:def __init__(self, root):self.root = rootself.root.title("高级自动备份工具")self.root.geometry("650x450")# 初始化变量self.is_auto_backup_running = Falseself.total_files = 0self.copied_files = 0self.backup_mode = tk.StringVar(value="full") # 备份模式# 创建界面组件self.create_widgets()self.setup_logging()def setup_logging(self):"""初始化日志系统"""self.log_path = os.path.join(os.getcwd(), "backup_log.txt")if not os.path.exists(self.log_path):with open(self.log_path, "w") as f:f.write("备份日志记录\n\n")def create_widgets(self):# 创建主容器main_frame = ttk.Frame(self.root)main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)# 源文件夹选择source_frame = ttk.LabelFrame(main_frame, text="源目录设置")source_frame.grid(row=0, column=0, columnspan=3, sticky="we", pady=5)self.source_entry = ttk.Entry(source_frame, width=50)self.source_entry.grid(row=0, column=0, padx=5, pady=5)ttk.Button(source_frame, text="浏览...", command=self.select_source).grid(row=0, column=1, padx=5)# 目标文件夹选择target_frame = ttk.LabelFrame(main_frame, text="目标目录设置")target_frame.grid(row=1, column=0, columnspan=3, sticky="we", pady=5)self.target_entry = ttk.Entry(target_frame, width=50)self.target_entry.grid(row=0, column=0, padx=5, pady=5)ttk.Button(target_frame, text="浏览...", command=self.select_target).grid(row=0, column=1, padx=5)# 过滤设置filter_frame = ttk.LabelFrame(main_frame, text="文件过滤设置")filter_frame.grid(row=2, column=0, sticky="we", pady=5, padx=5)ttk.Label(filter_frame, text="包含模式(逗号分隔):").grid(row=0, column=0)self.include_pattern = ttk.Entry(filter_frame)self.include_pattern.grid(row=0, column=1, padx=5)ttk.Label(filter_frame, text="排除模式(逗号分隔):").grid(row=1, column=0)self.exclude_pattern = ttk.Entry(filter_frame)self.exclude_pattern.grid(row=1, column=1, padx=5)# 备份设置setting_frame = ttk.LabelFrame(main_frame, text="备份设置")setting_frame.grid(row=2, column=1, sticky="we", pady=5, padx=5)ttk.Label(setting_frame, text="间隔(分钟):").grid(row=0, column=0)self.interval_entry = ttk.Entry(setting_frame, width=8)self.interval_entry.grid(row=0, column=1, padx=5)self.interval_entry.insert(0, "60")ttk.Radiobutton(setting_frame, text="完整备份", variable=self.backup_mode, value="full").grid(row=1, column=0)ttk.Radiobutton(setting_frame, text="增量备份", variable=self.backup_mode, value="incremental").grid(row=1,column=1)# 进度条self.progress = ttk.Progressbar(main_frame, orient=tk.HORIZONTAL, mode='determinate')self.progress.grid(row=3, column=0, columnspan=3, sticky="we", pady=10)# 按钮区域btn_frame = ttk.Frame(main_frame)btn_frame.grid(row=4, column=0, columnspan=3, pady=10)ttk.Button(btn_frame, text="立即备份", command=self.manual_backup).pack(side=tk.LEFT, padx=5)self.auto_btn = ttk.Button(btn_frame, text="开始自动备份", command=self.toggle_auto_backup)self.auto_btn.pack(side=tk.LEFT, padx=5)ttk.Button(btn_frame, text="查看日志", command=self.show_logs).pack(side=tk.LEFT, padx=5)# 状态栏self.status_label = ttk.Label(main_frame, text="状态: 就绪", relief=tk.SUNKEN)self.status_label.grid(row=5, column=0, columnspan=3, sticky="we")def select_source(self):path = filedialog.askdirectory()if path:self.source_entry.delete(0, tk.END)self.source_entry.insert(0, path)def select_target(self):path = filedialog.askdirectory()if path:self.target_entry.delete(0, tk.END)self.target_entry.insert(0, path)def manual_backup(self):threading.Thread(target=self.perform_backup, daemon=True).start()def should_include(self, file_path):"""文件过滤逻辑"""include = self.include_pattern.get().strip()exclude = self.exclude_pattern.get().strip()filename = os.path.basename(file_path)# 包含规则if include:patterns = [p.strip() for p in include.split(",")]if not any(fnmatch.fnmatch(filename, p) for p in patterns):return False# 排除规则if exclude:patterns = [p.strip() for p in exclude.split(",")]if any(fnmatch.fnmatch(filename, p) for p in patterns):return Falsereturn Truedef get_file_hash(self, file_path):"""计算文件哈希值(用于增量备份)"""hasher = hashlib.md5()with open(file_path, 'rb') as f:while chunk := f.read(8192):hasher.update(chunk)return hasher.hexdigest()def perform_backup(self):"""执行备份的核心方法"""try:source = self.source_entry.get()target = self.target_entry.get()if not source or not target:messagebox.showerror("错误", "请先选择源文件夹和目标文件夹")returntimestamp = datetime.now().strftime("%Y%m%d_%H%M%S")backup_folder = os.path.join(target, f"backup_{timestamp}")os.makedirs(backup_folder, exist_ok=True)# 获取文件列表并过滤all_files = []for root, dirs, files in os.walk(source):for file in files:full_path = os.path.join(root, file)if self.should_include(full_path):all_files.append(full_path)self.total_files = len(all_files)self.copied_files = 0self.progress['maximum'] = self.total_filesself.progress['value'] = 0# 记录日志log_entry = {'timestamp': datetime.now().strftime("%Y-%m-%d %H:%M:%S"),'source': source,'target': backup_folder,'mode': self.backup_mode.get(),'status': 'success','files': 0}# 执行备份for file_path in all_files:if not self.is_auto_backup_running and self.backup_mode.get() == "incremental":break # 允许取消增量备份rel_path = os.path.relpath(file_path, source)dest_path = os.path.join(backup_folder, rel_path)os.makedirs(os.path.dirname(dest_path), exist_ok=True)# 增量备份检查if self.backup_mode.get() == "incremental":if os.path.exists(dest_path):src_hash = self.get_file_hash(file_path)dst_hash = self.get_file_hash(dest_path)if src_hash == dst_hash:continueshutil.copy2(file_path, dest_path)self.copied_files += 1self.update_progress()log_entry['files'] = self.copied_filesself.log_backup(log_entry)self.update_status(f"备份完成:复制 {self.copied_files}/{self.total_files} 个文件")except Exception as e:self.update_status(f"备份失败:{str(e)}")messagebox.showerror("错误", str(e))log_entry['status'] = 'failed'log_entry['error'] = str(e)self.log_backup(log_entry)def update_progress(self):"""更新进度条"""self.progress['value'] = self.copied_filesself.root.update_idletasks()def log_backup(self, entry):"""记录备份日志"""with open(self.log_path, "a") as f:f.write(f"[{entry['timestamp']}] {entry['mode'].upper()}备份 "f"源目录: {entry['source']}\n目标目录: {entry['target']}\n"f"状态: {entry['status'].upper()} 文件数: {entry['files']}\n")if 'error' in entry:f.write(f"错误信息: {entry['error']}\n")f.write("-" * 50 + "\n")def show_logs(self):"""显示日志窗口"""log_win = tk.Toplevel(self.root)log_win.title("备份日志")text_area = tk.Text(log_win, wrap=tk.WORD, width=80, height=20)scroll = ttk.Scrollbar(log_win, command=text_area.yview)text_area.configure(yscrollcommand=scroll.set)with open(self.log_path, "r") as f:text_area.insert(tk.END, f.read())text_area.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)scroll.pack(side=tk.RIGHT, fill=tk.Y)def toggle_auto_backup(self):if not self.is_auto_backup_running:try:interval = int(self.interval_entry.get()) * 60if interval <= 0:raise ValueErrorexcept ValueError:messagebox.showerror("错误", "请输入有效的正整数分钟数")returnself.is_auto_backup_running = Trueself.auto_btn.config(text="停止自动备份")self.update_status("自动备份已启动...")self.auto_backup_thread = threading.Thread(target=self.auto_backup_loop, args=(interval,), daemon=True)self.auto_backup_thread.start()else:self.is_auto_backup_running = Falseself.auto_btn.config(text="开始自动备份")self.update_status("自动备份已停止")def auto_backup_loop(self, interval):while self.is_auto_backup_running:self.perform_backup()for _ in range(interval):if not self.is_auto_backup_running:returntime.sleep(1)def update_status(self, message):self.status_label.config(text=f"状态: {message}")if __name__ == "__main__":root = tk.Tk()app = BackupApp(root)root.mainloop()
完毕!!感谢您的收看
----------★★跳转到历史博文集合★★----------
我的零基础Python教程,Python入门篇 进阶篇 视频教程 Py安装py项目 Python模块 Python爬虫 Json Xpath 正则表达式 Selenium Etree CssGui程序开发 Tkinter Pyqt5 列表元组字典数据可视化 matplotlib 词云图 Pyecharts 海龟画图 Pandas Bug处理 电脑小知识office自动化办公 编程工具 NumPy Pygame
相关文章:

Python项目73:自动化文件备份系统1.0(tkinter)
主要功能说明: 1.界面组件:源文件夹和目标文件夹选择(带浏览按钮),备份间隔时间设置(分钟),立即备份按钮,自动备份切换按钮,状态栏显示备份状态。 2.进度条显…...

C++:扫雷游戏
一.扫雷游戏项目设计 1.文件结构设计 首先我们要先定义三个文件 ①test.c //文件中写游戏的测试逻辑 ②game.c //文件中写游戏中函数的实现等 ③game.h //文件中写游戏需要的数据类型和函数声明等 2.扫雷游戏的主体结构 使⽤控制台实现经典的扫雷游戏 •游戏可以通过菜单…...

使用xlwings将excel表中将无规律的文本型数字批量转化成真正的数字
之前我写了一篇文章excel表中将无规律的文本型数字批量转化成真正的数字-CSDN博客 是使用excel自带的操作,相对繁琐。 今天使用xlwings操作,表格如下(有真正的数字,也有文本型数字,混在在一起)࿱…...

文件包含 任意文件读取
文件处理漏洞--文件包含 - wizard骑士 - 博客园 1,什么是文件包含 程序开发人员一般会吧重复使用的函数写道单个文件中,需要使用某个函数时直接调用此文件,无需再次编写,文件调用的过程就是文件包含,所以将包含的文件…...

缓存套餐-01.Spring Cache介绍和常用注解
一.Spring Cache 要使用直接导入坐标即可。 如何选择底层的缓存实现呢?只要导入对应的缓存坐标即可。如果要使用redis作为缓存实现,那么只需要导入redis的maven坐标。 二.常用注解 Cacheable:不光往缓存中写缓存数据,而且会从缓…...

C++类与对象—下:夯实面向对象编程的阶梯
9. 赋值运算符重载 9.1 运算符重载 在 C 里,运算符重载能够让自定义类型的对象像内置类型那样使用运算符,这极大地提升了代码的可读性与可维护性。运算符重载本质上是一种特殊的函数,其函数名是 operator 加上要重载的运算符。 下面是运算…...
MCP认证全解析:从零到微软认证专家
MCP认证全解析:从零到微软认证专家 什么是MCP认证? Microsoft Certified Professional(MCP)是由微软官方颁发的技术认证,旨在验证IT从业者在微软技术栈(如Azure、Windows Server、SQL Server等࿰…...
裸辞8年前端的面试笔记——JavaScript篇(一)
裸辞后的第二个月开始准备找工作,今天是第三天目前还没有面试,现在的行情是一言难尽,都在疯狂的压价。 下边是今天复习的个人笔记 一、事件循环 JavaScript 的事件循环(Event Loop)是其实现异步编程的关键机制。 从…...
TCP 与 UDP报文
** TCP 与 UDP报文** 1. 引言 在网络通信中,TCP(传输控制协议) 和 UDP(用户数据报协议) 是两种最核心的传输层协议。它们各自适用于不同的场景,理解其工作原理对开发高性能网络应用至关重要。本文将详细解…...
开上“Python跑的车”——自动驾驶数据可视化的落地之道
开上“Python跑的车”——自动驾驶数据可视化的落地之道 一、自动驾驶离不开“看得见”的智能 在智能汽车时代,自动驾驶已然不是“炫技”标签,而是一场技术实力的全面拉锯战。而在这场战役中,有一个极其关键但常被忽略的领域,叫做: 数据可视化(Data Visualization)。 为…...

Linux中安装mysql8,转载及注意事项
一、先前往官网下载mysql8 下载地址: https://dev.mysql.com/downloads/选择Linux 二、删除Linux中的mysql(如果有的话),上传安装包 1、先查看mysql是否存在,命令如下: rpm -qa|grep -i mysql如果使用这…...
可以下载blender/fbx格式模型网站
glbxz.com glbxz.com可以下载blender/fbx格式模型。当然里面有免费的...

SpringBoot的汽车商城后台管理系统源码开发实现
概述 汽车商城后台管理系统专为汽车4S店和经销商设计,提供全面的汽车管理系统解决方案。 主要内容 1. 核心功能模块 系统提供以下主要功能: 销售管理:记录销售信息,跟踪交易进度客户管理:维护客户…...
从入门到深入:Vue.js 学习全攻略
一、Vue.js 入门基础 (一)Vue.js 简介与环境搭建 Vue.js 是一套用于构建用户界面的渐进式 JavaScript 框架,所谓渐进式,意味着开发者可以根据项目需求,灵活地选择使用 Vue 的功能。它既可以嵌入到简单的 HTML 页面中…...
C++八股--6--mysql 日志与并发控制
这里向大家介绍一下数据库基础:共分为以下章节 10前序.日志系统 这是数据库的核心。我放到首页来介绍,给大家一个前置概念,方便进行更好的学习 日志文件我们用来记录事务对数据库更新操作的文件,分为以记录为单位的文件和数据块…...

DeepSeek实战--手搓实现Agent
1.背景 要学习AI agent,只会用agent 框架,还不够,一旦框架出现问题,没法快速的排查出问题。 学习就应该“知其然,更应该知其所以然” ,今天我们就用编码的方式实现一个简单的agent 。我们模拟一套AI学生评…...
Hutool的`BeanUtil.toBean`方法详解
BeanUtil.toBean是Hutool工具包中一个非常实用的JavaBean转换工具方法,它能够方便地将一个对象(通常是Map或另一个JavaBean)转换为目标类型的JavaBean实例。 方法签名 public static <T> T toBean(Object source, Class<T> tar…...

线性代数——行列式⭐
目录 一、行列式的定义⭐ 1-1、三阶行列式练习 1-2、下面介绍下三角行列式、上三角行列式、对角行列式 编辑 二、行列式的性质 2-1、性质1,2,3,4,5,6 编辑 2-2、性质7 2- 3、拉普拉斯定理、克莱姆法则 三…...

iPhone手机连接WiFi异常解决方法
iPhone手机连接WiFi异常解决方法 一、问题现象二、iPhone连不上可能的原因三、基础排查与快速修复第一步:重启大法第二步:忽略网络,重新认证第三步:关闭“私有无线局域网地址”第四步:修改DNS服务器第五步:还原网络设置四、路由器端排查及设置关闭MAC地址过滤或添加到白名…...
Spark缓存
生活中缓存容量受成本和体积限制(比如 CPU 缓存只有几 MB 到几十 MB),但会通过算法(如 “最近最少使用” 原则)智能决定存什么,确保存的是 “最可能被用到的数据”。 1. 为什么需要缓存? 惰性执…...
计算机视觉与深度学习 | 基于Transformer的低照度图像增强技术
基于Transformer的低照度图像增强技术通过结合Transformer的全局建模能力和传统图像增强理论(如Retinex),在保留颜色信息、抑制噪声和平衡亮度方面展现出显著优势。以下是其核心原理、关键公式及典型代码实现: 一、原理分析 1. 全局依赖建模与局部特征融合 Transformer的核…...

学习设计模式《八》——原型模式
一、基础概念 原型模式的本质是【克隆生成对象】; 原型模式的定义:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象 。 原型模式的功能: 1、通过克隆来创建新的对象实例; 2、为克隆出来的新对象实例复制…...

疗愈服务预约小程序源码介绍
基于ThinkPHP、FastAdmin和UniApp开发的疗愈服务预约小程序源码,这款小程序在功能设计和用户体验上都表现出色,为疗愈行业提供了一种全新的服务模式。 该小程序源码采用了ThinkPHP作为后端框架,保证了系统的稳定性和高效性。同时,…...
如何通过外网访问内网?对比5个简单的局域网让互联网连接方案
在实际应用中,常常需要从外网访问内网资源,如远程办公访问公司内部服务器、在家访问家庭网络中的设备等。又或者在本地内网搭建的项目应用需要提供互联网服务。以下介绍几种常见的外网访问内网、内网提供公网连接实现方法参考。 一、公网IP路由器端口映…...
Linux 服务器静态 IP 配置初始化指南
✅ 第一步:确认网络管理方式 运行以下命令判断系统使用的网络管理服务: # 检查 NetworkManager 是否活跃 systemctl is-active NetworkManager# 检查 network(旧服务)是否活跃 systemctl is-active network或者检查配置路径&…...

【随笔】Google学术:but your computer or network may be sending automated queries.
文章目录 一、问题复述二、问题原因三、解决 前提:你的xxx是自己做的,你自己可以管理,而不是用的那些劣质✈场。 一、问题复述 🟢如下图所示:可以打开谷歌学术,但是一搜索就是这个界面。 二、问题原因 …...

长事务:数据库中的“隐形炸弹“——金仓数据库运维避坑指南
引言:凌晨三点的告警 "张工!生产库又告警了!"凌晨三点的电话铃声总是格外刺耳。运维团队发现数据库频繁进入单用户模式,排查发现某核心表的年龄值(Age)已突破20亿大关。经过一夜奋战,…...

ubuntu nobel + qt5.15.2 设置qss语法识别正确
问题展示 解决步骤 首选项里面的高亮怎么编辑选择都没用。如果已经有generic-highlighter和css.xml,直接修改css.xml文件最直接! 在generic-highlighter目录下找到css.xml文件,位置是:/opt/Qt/Tools/QtCreator/share/qtcreator/…...
优化01-统计信息
Oracle 的统计信息是数据库优化器生成高效执行计划的核心依据。它记录了数据库对象(如表、索引、列等)的元数据信息,帮助优化器评估查询成本并选择最优执行路径。以下是关于 Oracle 统计信息的详细介绍: 一、统计信息的分类 表统…...

Unity-Socket通信实例详解
今天我们来讲解socket通信。 首先我们需要知道什么是socket通信: Socket本质上就是一个个进程之间网络通信的基础,每一个Socket由IP端口组成,熟悉计网的同学应该知道IP主要是应用于IP协议而端口主要应用于TCP协议,这也证明了Sock…...