根本原因是编辑器保存采用“临时文件+原子重命名”流程,实际触发on_moved而非on_created;需同时监听on_created、on_modified、on_moved,并对新目录手动schedule,注意inotify限制及事件去抖。

Watchdog 能可靠监控文件变动,但默认行为和事件触发逻辑容易让人误以为“没反应”——根本原因通常是事件类型没选对、递归设置不匹配,或忽略了操作系统底层的 inotify 限制。
为什么 FileSystemEventHandler 看不到新建文件?
Watchdog 默认只监听 on_created 和 on_modified 这类“显式事件”,但很多编辑器(如 VS Code、Sublime)保存文件时实际走的是“先写临时文件 + 原子重命名”流程,最终触发的是 on_moved,而非 on_created。
- 务必同时覆盖
on_created、on_modified、on_moved三个方法 -
on_moved的event.is_directory为False且event.dest_path是最终文件路径,这才是真实落盘位置 - 如果只监听文本文件,记得在 handler 中用
os.path.splitext(event.src_path)[1]或event.dest_path过滤后缀
递归监控子目录时 recursive=True 不生效?
不是参数失效,而是 Watchdog 初始化时只扫描当前层级的子目录结构;如果后续动态创建了新子目录(比如程序运行中 mkdir logs/2024/06),默认不会自动加入监控范围。
- 必须手动调用
observer.schedule(handler, path="logs/2024/06", recursive=True)才能补上 - 更稳妥的做法是:监听根目录时设
recursive=True,并在on_created里判断event.is_directory,对新目录再次observer.schedule(...) - 注意 Linux 下 inotify 有
/proc/sys/fs/inotify/max_user_watches限制,子目录太多可能报OSError: [Errno 25] Inappropriate ioctl for device,需调高该值
如何避免重复触发 on_modified?
文本编辑器频繁写入(如每秒多次保存)、IDE 自动格式化、Git 切换分支等场景,会导致单个逻辑操作引发数十次 on_modified,极易造成处理逻辑被反复执行甚至崩溃。
立即学习“Python免费学习笔记(深入)”;
- 加简单去抖:用
threading.Timer延迟执行,收到首个修改事件后启动 1 秒定时器,期间新事件到来就 cancel 并重启 - 记录文件 mtime + size 组合哈希,仅当变化时才真正处理(比单纯依赖事件更稳)
- 慎用
on_modified做耗时操作(如解析 JSON);优先用on_moved或on_closed_write(需用PollingObserver)作为“写入完成”信号
Watchdog 的核心难点不在 API 调用,而在理解文件系统事件的真实链条——你看到的“保存”,操作系统可能拆成 3 次 write + 1 次 rename + 2 次 chmod。监控逻辑得跟着这个链条走,而不是盯着编辑器界面上的那个“保存按钮”。


















