watchdog监听器启动后没反应,需检查事件处理器是否注册及主线程是否被阻塞;必须显式调用observer.join()或time.sleep()维持进程存活,否则程序退出导致监听终止。

watchdog监听器启动后没反应?检查事件循环和阻塞点
watchdog本身不自动运行事件循环,Observer 启动后必须保持主线程活跃,否则程序立即退出,监听自然失效。
- 常见错误:调用
observer.start()后直接结束脚本(比如没加time.sleep()或没接observer.join()) - 推荐做法:用
observer.join()阻塞主线程,等待中断信号;若需响应 Ctrl+C,应配合signal.signal(signal.SIGINT, ...)安全退出 - 注意
observer.start()是异步的,后续代码会立刻执行,不能依赖它“等就绪”
为什么文件修改两次才触发 FileSystemEventHandler.on_modified?
这是操作系统和编辑器行为导致的典型现象,不是 watchdog 的 bug。多数编辑器(如 VS Code、Sublime)保存时会先写临时文件,再原子替换原文件,过程包含:on_created(临时文件)、on_deleted(原文件)、on_moved(重命名临时→目标),最后才是 on_modified(实际内容变更)。
- 真正关心“内容是否变”,应监听
on_modified+on_moved,并过滤掉临时文件路径(如以.swp、~、.tmp结尾) - 避免重复处理:对同一路径加时间窗口去重(例如 100ms 内重复
on_modified忽略) - Windows 下还可能因索引服务或杀软干扰,导致事件延迟或丢失
如何只监听指定后缀的文件变动?别在 handler 里硬过滤
在 on_created 或 on_modified 回调里用 os.path.splitext(path)[1] 判断后缀,看似简单,但会浪费 CPU 处理大量无关事件。watchdog 提供更高效的方式:
- 使用
PatternMatchingEventHandler,构造时传入patterns=["*.py", "*.json"],它会在内核事件分发前就过滤 - 注意
ignore_patterns和ignore_directories也建议一并设置,避免监听 .git、__pycache__ 等目录 - 如果需要动态更新监听规则,得停掉
Observer,重建EventHandler并重新schedule(),watchdog 不支持运行时热更新 patterns
Linux 下监听深层嵌套目录失败?关注 inotify 限制
watchdog 在 Linux 底层依赖 inotify,而 inotify 对单用户可监控的总 inotify 实例数、每个实例的 watch 数量都有默认上限(通常是 8192)。深层嵌套或大量子目录容易触发 OSError: [Errno 24] Too many open files。
立即学习“Python免费学习笔记(深入)”;
- 查当前限制:
cat /proc/sys/fs/inotify/max_user_watches - 临时提升:
sudo sysctl fs.inotify.max_user_watches=524288 - 永久生效:写入
/etc/sysctl.conf,追加fs.inotify.max_user_watches=524288 - 更稳妥的做法是避免递归监听整个大目录树,改用
recursive=False,仅监听关键层级,再按需手动添加子目录 watch
on_modified 处理花了 2 秒,而新事件每 100ms 来一个,队列就会堆积,最终丢事件或卡死。务必让 handler 尽量轻量,重逻辑扔进线程池或消息队列。


















