可行但需规避编辑器原子写导致的重复/漏触发问题:on_modified多次触发源于vs code等编辑器“写临时文件+原子重命名”机制,应优先监听on_moved/on_created、加1–2秒去抖、备份前校验mtime并捕获permissionerror重试。

直接用 watchdog 监控文件夹变动并触发备份是可行的,但默认行为不保证“每次修改都可靠触发一次备份”——尤其在快速连续写入(如编辑器保存、Git pull)时容易漏事件或重复触发。
为什么 FileSystemEventHandler 的 on_modified 会误触发多次?
Linux/macOS 下很多编辑器(VS Code、Sublime)保存文件时实际执行的是“原子替换”:先写临时文件,再 rename 覆盖原文件。这会先后触发 on_created + on_deleted + on_modified,甚至多个 on_modified。Windows 上则可能因缓存延迟导致单次修改被拆成多次通知。
- 不要在
on_modified里直接调用备份逻辑,否则一个保存动作可能触发 3–5 次备份 - 优先监听
on_moved(对应 rename)和on_created,它们更接近“文件已就绪”的信号 - 对同一路径加 1–2 秒去抖(debounce),比如用
threading.Timer延迟执行,取消前序未触发的定时器
如何避免备份过程中文件被再次修改导致冲突?
备份不是原子操作,若源文件在 shutil.copy2 执行中途被改写,可能产生损坏副本或 PermissionError(Windows 下常见)。
Python 3.14.2是Python编程语言在2025年12月5日发布的稳定版本,属于3.14系列的第二个维护更新。该版本包含了18项修复,重点解决了多进程、数据类及正则表达式等模块的回归问题,并修复了CVE-2025-12084等安全漏洞。此版本标志着自由线程模式(移除GIL)正式获得官方支持,是Python发展的重要里程碑。
- 备份前先用
os.stat(path).st_mtime记录时间戳,备份后再次检查是否变化;若变了,跳过本次或重试 - 对正在被写入的文件(如日志、数据库文件),用
try/except PermissionError捕获并重试 1–2 次,间隔 0.5 秒 - 不要用
shutil.copytree直接同步整个目录——它不处理增量,且无法跳过正在写入的文件;改用遍历 + 单文件判断
怎样让 watchdog 在后台稳定运行不崩溃?
watchdog 默认使用 inotify(Linux)或 FSEvents(macOS),但资源耗尽或权限不足时会静默退出,进程看似还在,实则不再监听。
- 启动后立即检查
observer.is_alive(),并在主循环中每 10 秒轮询一次 - 捕获
KeyboardInterrupt和SystemExit,确保observer.stop()+observer.join()被调用 - 避免在事件回调里做耗时操作(如压缩、上传);用
queue.Queue把待备份路径丢给独立线程处理 - Windows 上注意路径长度限制:如果监控路径超过 260 字符,需在脚本开头加
import ctypes; ctypes.windll.kernel32.SetConsoleOutputCP(65001)并启用长路径支持
真正难的不是“监听到就备份”,而是应对编辑器行为差异、文件锁、网络中断这些现实干扰。把去抖、状态校验、错误重试做成标配,比堆功能更重要。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










