watchdog 是监控目录变化最可靠的 python 方案,它跨平台封装底层 api,需避免轮询、合理处理事件类型、安全调用外部脚本、妥善管理守护进程及事件丢失问题。

用 watchdog 监控目录变化最可靠
Python 标准库没有开箱即用的跨平台目录监听方案,watchdog 是目前最成熟的选择。它封装了 Linux 的 inotify、macOS 的 FSEvents 和 Windows 的 ReadDirectoryChangesW,避免自己写平台适配逻辑。
安装只需:
pip install watchdog
- 不要用
time.sleep()+os.listdir()轮询——耗 CPU、延迟高、漏事件 - 避免直接调用
subprocess启动脚本时不设超时或捕获异常,否则子进程卡住会阻塞整个监听器 -
watchdog默认递归监听子目录,如只需顶层,初始化Observer时传recursive=False
定义事件处理器要区分具体动作类型
不是所有变化都要触发任务。比如你只想在文件写完后运行校验脚本,那得监听 FileCreatedEvent 或 FileModifiedEvent,而不是 DirCreatedEvent。
关键点:
-
on_created在文件/目录刚创建时触发,但此时内容可能未写完(尤其大文件),更适合轻量操作(如打日志) -
on_modified频繁触发(编辑器保存常触发多次),建议加简单去重:记录event.src_path+ 时间戳,1 秒内重复忽略 - 真正需要“文件就绪”语义时,用
on_closed_write(需继承PatternMatchingEventHandler并重写该方法)
触发外部脚本必须处理路径和环境隔离
直接 subprocess.run(['./deploy.sh']) 很危险:当前工作目录不固定、环境变量缺失、权限不足都可能导致失败。
- 始终用绝对路径调用脚本,例如
subprocess.run(['/opt/scripts/deploy.sh', event.src_path]) - 显式指定
cwd和env,比如env=os.environ.copy()确保继承父进程环境 - 加
timeout=30防止脚本卡死,捕获subprocess.TimeoutExpired做降级处理(如发告警) - 别把敏感参数拼进命令行,改用
stdin=subprocess.PIPE或临时配置文件传递
守护进程化时注意信号和资源释放
一旦部署为长期运行的服务,KeyboardInterrupt 不再可靠,必须响应系统信号并清理资源。
- 注册
signal.SIGTERM处理器,在退出前调用observer.stop()和observer.join() - 避免在事件处理器里做阻塞操作(如同步 HTTP 请求),否则会堆积事件队列;改用线程池或异步队列
- 日志务必用
logging而非print,否则 systemd 或 supervisor 捕获不到输出
最难调试的是事件丢失——常见于高频率写入(如 rsync 同步大量小文件),这时得调大 inotify 的 max_user_watches,或改用 AsyncIOObserver 提升吞吐。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











